How to update only one field using Entity Framework?

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

Here\'s the table

Users

UserId
UserName
Password
EmailAddress

and the code..



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

    You have basically two options:

    • go the EF way all the way, in that case, you would
      • load the object based on the userId provided - the entire object gets loaded
      • update the password field
      • save the object back using the context's .SaveChanges() method

    In this case, it's up to EF how to handle this in detail. I just tested this, and in the case I only change a single field of an object, what EF creates is pretty much what you'd create manually, too - something like:

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

    So EF is smart enough to figure out what columns have indeed changed, and it will create a T-SQL statement to handle just those updates that are in fact necessary.

    • you define a stored procedure that does exactly what you need, in T-SQL code (just update the Password column for the given UserId and nothing else - basically executes UPDATE dbo.Users SET Password = @Password WHERE UserId = @UserId) and you create a function import for that stored procedure in your EF model and you call this function instead of doing the steps outlined above
    0 讨论(0)
  • 2020-11-22 09:31
    public async Task<bool> UpdateDbEntryAsync(TEntity entity, params Expression<Func<TEntity, object>>[] properties)
    {
        try
        {
            this.Context.Set<TEntity>().Attach(entity);
            EntityEntry<TEntity> entry = this.Context.Entry(entity);
            entry.State = EntityState.Modified;
            foreach (var property in properties)
                entry.Property(property).IsModified = true;
            await this.Context.SaveChangesAsync();
            return true;
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    
    0 讨论(0)
  • 2020-11-22 09:32

    I'm late to the game here, but this is how I am doing it, I spent a while hunting for a solution I was satisified with; this produces an UPDATE statement ONLY for the fields that are changed, as you explicitly define what they are through a "white list" concept which is more secure to prevent web form injection anyway.

    An excerpt from my ISession data repository:

    public bool Update<T>(T item, params string[] changedPropertyNames) where T 
      : class, new()
    {
        _context.Set<T>().Attach(item);
        foreach (var propertyName in changedPropertyNames)
        {
            // If we can't find the property, this line wil throw an exception, 
            //which is good as we want to know about it
            _context.Entry(item).Property(propertyName).IsModified = true;
        }
        return true;
    }
    

    This could be wrapped in a try..catch if you so wished, but I personally like my caller to know about the exceptions in this scenario.

    It would be called in something like this fashion (for me, this was via an ASP.NET Web API):

    if (!session.Update(franchiseViewModel.Franchise, new[]
        {
          "Name",
          "StartDate"
      }))
      throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
    
    0 讨论(0)
  • 2020-11-22 09:36

    Entity framework tracks your changes on objects that you queried from database via DbContext. For example if you DbContext instance name is dbContext

    public void ChangePassword(int userId, string password){
         var user = dbContext.Users.FirstOrDefault(u=>u.UserId == userId);
         user.password = password;
         dbContext.SaveChanges();
    }
    
    0 讨论(0)
  • 2020-11-22 09:36
    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();
      }
    }
    
    0 讨论(0)
  • 2020-11-22 09:37

    I use ValueInjecter nuget to inject Binding Model into database Entity using following:

    public async Task<IHttpActionResult> Add(CustomBindingModel model)
    {
       var entity= await db.MyEntities.FindAsync(model.Id);
       if (entity== null) return NotFound();
    
       entity.InjectFrom<NoNullsInjection>(model);
    
       await db.SaveChangesAsync();
       return Ok();
    }
    

    Notice the usage of custom convention that doesn't update Properties if they're null from server.

    ValueInjecter v3+

    public class NoNullsInjection : LoopInjection
    {
        protected override void SetValue(object source, object target, PropertyInfo sp, PropertyInfo tp)
        {
            if (sp.GetValue(source) == null) return;
            base.SetValue(source, target, sp, tp);
        }
    }
    

    Usage:

    target.InjectFrom<NoNullsInjection>(source);
    

    Value Injecter V2

    Lookup this answer

    Caveat

    You won't know whether the property is intentionally cleared to null OR it just didn't have any value it. In other words, the property value can only be replaced with another value but not cleared.

    0 讨论(0)
提交回复
热议问题