这是表格

用户

UserId
UserName
Password
EmailAddress

还有代码..

public void ChangePassword(int userId, string password){
//code to update the password..
}

当前回答

你基本上有两个选择:

一直用EF的方法,在这种情况下,你会 根据提供的userId加载对象——整个对象都会被加载 更新密码字段 使用上下文的.SaveChanges()方法将对象保存回来

在这种情况下,具体如何处理就取决于EF了。我刚刚测试了这个,在这种情况下,我只改变一个对象的一个字段,EF创建的几乎是你手动创建的,太像:

`UPDATE dbo.Users SET Password = @Password WHERE UserId = @UserId`

因此,EF足够聪明,可以找出哪些列确实发生了更改,并且它将创建一个T-SQL语句来处理实际上必要的更新。

你在T-SQL代码中定义了一个完全满足你需要的存储过程(只更新给定UserId的Password列,其他什么都不做——基本上执行update dbo。Users SET Password = @Password WHERE UserId = @UserId),然后在EF模型中为该存储过程创建一个函数导入,并且调用这个函数,而不是执行上面概述的步骤

其他回答

_context.Users.UpdateProperty(p => p.Id, request.UserId, new UpdateWrapper<User>()
                {
                    Expression = p => p.FcmId,Value = request.FcmId
                });
   await _context.SaveChangesAsync(cancellationToken);

Update Property是一个扩展方法

public static void UpdateProperty<T, T2>(this DbSet<T> set, Expression<Func<T, T2>> idExpression,
            T2 idValue,
            params UpdateWrapper<T>[] updateValues)
            where T : class, new()
        {
            var entity = new T();
            var attach = set.Attach(entity);
            attach.Property(idExpression).IsModified = false;
            attach.Property(idExpression).OriginalValue = idValue;
            foreach (var update in updateValues)
            {
                attach.Property(update.Expression).IsModified = true;
                attach.Property(update.Expression).CurrentValue = update.Value;
            }
        }

Update Wrapper是一个类

public class UpdateWrapper<T>
    {
        public Expression<Func<T, object>> Expression  { get; set; }
        public object Value { get; set; }
    }

我用这个:

实体:

public class Thing 
{
    [Key]
    public int Id { get; set; }
    public string Info { get; set; }
    public string OtherStuff { get; set; }
}

数据库上下文:

public class MyDataContext : DbContext
{
    public DbSet<Thing > Things { get; set; }
}

访问器代码:

MyDataContext ctx = new MyDataContext();

// FIRST create a blank object
Thing thing = ctx.Things.Create();

// SECOND set the ID
thing.Id = id;

// THIRD attach the thing (id is not marked as modified)
db.Things.Attach(thing); 

// FOURTH set the fields you want updated.
thing.OtherStuff = "only want this field updated.";

// FIFTH save that thing
db.SaveChanges();
public void ChangePassword(int userId, string password)
{
  var user = new User{ Id = userId, Password = password };
  using (var db = new DbContextName())
  {
    db.Entry(user).State = EntityState.Added;
    db.SaveChanges();
  }
}

I know this is an old thread but I was also looking for a similar solution and decided to go with the solution @Doku-so provided. I'm commenting to answer the question asked by @Imran Rizvi , I followed @Doku-so link that shows a similar implementation. @Imran Rizvi's question was that he was getting an error using the provided solution 'Cannot convert Lambda expression to Type 'Expression> [] ' because it is not a delegate type'. I wanted to offer a small modification I made to @Doku-so's solution that fixes this error in case anyone else comes across this post and decides to use @Doku-so's solution.

问题是Update方法中的第二个参数,

public int Update(T entity, Expression<Func<T, object>>[] properties). 

使用提供的语法调用此方法…

Update(Model, d=>d.Name, d=>d.SecondProperty, d=>d.AndSoOn); 

你必须在第二个参数前面加上'params'关键字。

public int Update(T entity, params Expression<Func<T, object>>[] properties)

或者如果你不想改变方法签名,那么要调用Update方法,你需要添加'new'关键字,指定数组的大小,然后最后使用集合对象初始化语法来更新每个属性,如下所示。

Update(Model, new Expression<Func<T, object>>[3] { d=>d.Name }, { d=>d.SecondProperty }, { d=>d.AndSoOn });

在@Doku-so的例子中,他指定了一个表达式数组,所以你必须在数组中传递属性来更新,因为数组你还必须指定数组的大小。为了避免这种情况,您还可以更改表达式参数,使用IEnumerable而不是数组。

下面是@Doku-so解决方案的实现。

public int Update<TEntity>(LcmsEntities dataContext, DbEntityEntry<TEntity> entityEntry, params Expression<Func<TEntity, object>>[] properties)
     where TEntity: class
    {
        entityEntry.State = System.Data.Entity.EntityState.Unchanged;

        properties.ToList()
            .ForEach((property) =>
            {
                var propertyName = string.Empty;
                var bodyExpression = property.Body;
                if (bodyExpression.NodeType == ExpressionType.Convert
                    && bodyExpression is UnaryExpression)
                {
                    Expression operand = ((UnaryExpression)property.Body).Operand;
                    propertyName = ((MemberExpression)operand).Member.Name;
                }
                else
                {
                    propertyName = System.Web.Mvc.ExpressionHelper.GetExpressionText(property);
                }

                entityEntry.Property(propertyName).IsModified = true;
            });

        dataContext.Configuration.ValidateOnSaveEnabled = false;

        return dataContext.SaveChanges();
    }

用法:

this.Update<Contact>(context, context.Entry(modifiedContact), c => c.Active, c => c.ContactTypeId);

@Doku-so提供了一种使用泛型的很酷的方法,我用这个概念来解决我的问题,但你不能使用@Doku-so的解决方案,在这篇文章和链接的帖子中,都没有人回答使用错误的问题。

实体框架跟踪您通过DbContext从数据库查询的对象的更改。例如,如果你的DbContext实例名是DbContext

public void ChangePassword(int userId, string password){
     var user = dbContext.Users.FirstOrDefault(u=>u.UserId == userId);
     user.password = password;
     dbContext.SaveChanges();
}