How to update only one field using Entity Framework?

前端 未结 16 1465
后悔当初
后悔当初 2020-11-22 09:09

Here\'s the table

Users

UserId
UserName
Password
EmailAddress

and the code..



        
相关标签:
16条回答
  • 2020-11-22 09:39

    While searching for a solution to this problem, I found a variation on GONeale's answer through Patrick Desjardins' blog:

    public int Update(T entity, Expression<Func<T, object>>[] properties)
    {
      DatabaseContext.Entry(entity).State = EntityState.Unchanged;
      foreach (var property in properties)
      {
        var propertyName = ExpressionHelper.GetExpressionText(property);
        DatabaseContext.Entry(entity).Property(propertyName).IsModified = true;
      }
      return DatabaseContext.SaveChangesWithoutValidation();
    }
    

    "As you can see, it takes as its second parameter an expression of a function. This will let use this method by specifying in a Lambda expression which property to update."

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

    ( A somewhat similar solution is also given here: https://stackoverflow.com/a/5749469/2115384 )

    The method I am currently using in my own code, extended to handle also (Linq) Expressions of type ExpressionType.Convert. This was necessary in my case, for example with Guid and other object properties. Those were 'wrapped' in a Convert() and therefore not handled by System.Web.Mvc.ExpressionHelper.GetExpressionText.

    public int Update(T entity, Expression<Func<T, object>>[] properties)
    {
        DbEntityEntry<T> entry = dataContext.Entry(entity);
        entry.State = EntityState.Unchanged;
        foreach (var property in properties)
        {
            string propertyName = "";
            Expression 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);
            }
            entry.Property(propertyName).IsModified = true;
        }
    
        dataContext.Configuration.ValidateOnSaveEnabled = false;
        return dataContext.SaveChanges();
    }
    
    0 讨论(0)
  • 2020-11-22 09:40

    In Entity Framework Core, Attach returns the entry, so all you need is:

    var user = new User { Id = userId, Password = password };
    db.Users.Attach(user).Property(x => x.Password).IsModified = true;
    db.SaveChanges();
    
    0 讨论(0)
  • 2020-11-22 09:42

    I was looking for same and finally I found the solution

    using (CString conn = new CString())
    {
        USER user = conn.USERs.Find(CMN.CurrentUser.ID);
        user.PASSWORD = txtPass.Text;
        conn.SaveChanges();
    }
    

    believe me it work for me like a charm.

    0 讨论(0)
  • 2020-11-22 09:43

    You can tell EF which properties have to be updated in this way:

    public void ChangePassword(int userId, string password)
    {
      var user = new User { Id = userId, Password = password };
      using (var context = new ObjectContext(ConnectionString))
      {
        var users = context.CreateObjectSet<User>();
        users.Attach(user);
        context.ObjectStateManager.GetObjectStateEntry(user)
          .SetModifiedProperty("Password");
        context.SaveChanges();
      }
    }
    
    0 讨论(0)
  • 2020-11-22 09:44
    _context.Users.UpdateProperty(p => p.Id, request.UserId, new UpdateWrapper<User>()
                    {
                        Expression = p => p.FcmId,Value = request.FcmId
                    });
       await _context.SaveChangesAsync(cancellationToken);
    

    Update Property is an extension method

    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;
                }
            }
    

    And Update Wrapper is a class

    public class UpdateWrapper<T>
        {
            public Expression<Func<T, object>> Expression  { get; set; }
            public object Value { get; set; }
        }
    
    0 讨论(0)
  • 2020-11-22 09:45

    Combining several suggestions I propose the following:

        async Task<bool> UpdateDbEntryAsync<T>(T entity, params Expression<Func<T, object>>[] properties) where T : class
        {
            try
            {
                var entry = db.Entry(entity);
                db.Set<T>().Attach(entity);
                foreach (var property in properties)
                    entry.Property(property).IsModified = true;
                await db.SaveChangesAsync();
                return true;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine("UpdateDbEntryAsync exception: " + ex.Message);
                return false;
            } 
        }
    

    called by

    UpdateDbEntryAsync(dbc, d => d.Property1);//, d => d.Property2, d => d.Property3, etc. etc.);
    

    Or by

    await UpdateDbEntryAsync(dbc, d => d.Property1);
    

    Or by

    bool b = UpdateDbEntryAsync(dbc, d => d.Property1).Result;
    
    0 讨论(0)
提交回复
热议问题