Exclude Property on Update in Entity Framework

后端 未结 5 1119
野性不改
野性不改 2020-11-28 04:53

I\'ve been looking for a proper way to mark a property to NOT be changed when updating a model in MVC.

For example, let\'s take this small model:

cla         


        
相关标签:
5条回答
  • 2020-11-28 05:17

    Create new model that will have limited set of properties that you want to update.

    I.e. if your entity model is:

    public class User
    {
        public int Id {get;set;}
        public string Name {get;set;}
        public bool Enabled {get;set;}
    }
    

    You can create custom view model that will allow user to change Name, but not Enabled flag:

    public class UserProfileModel
    {
       public int Id {get;set;}
       public string Name {get;set;}
    }
    

    When you want to do database update, you do the following:

    YourUpdateMethod(UserProfileModel model)
    {
        using(YourContext ctx = new YourContext())
        { 
            User user = new User { Id = model.Id } ;   /// stub model, only has Id
            ctx.Users.Attach(user); /// track your stub model
            ctx.Entry(user).CurrentValues.SetValues(model); /// reflection
            ctx.SaveChanges();
        }
    }
    

    When you call this method, you will update the Name, but Enabled property will remain unchanged. I used simple models, but I think you'll get the picture how to use it.

    0 讨论(0)
  • 2020-11-28 05:28

    Anyone looking for how to achieve this on EF Core. It's basically the same but your IsModified needs to be after you add the model to be updated.

    db.Update(model);
    db.Entry(model).Property(x => x.Token).IsModified = false;
    db.SaveChanges();
    
    0 讨论(0)
  • 2020-11-28 05:30

    I guess you don't want the property to be changed just in some cases, because if you are not going to use it never in your application, just remove it from your model.

    In case you want to use it just in some scenarios and avoid its "nullification" in the case above, you can try to:

    • Hide the parameter in the view with HiddenFor:

      @Html.HiddenFor(m => m.Token)

    This will make your original value to be kept unmodified and passed back to the controller.

    • Use TryUpdateModel: http://msdn.microsoft.com/en-us/library/dd460189(v=vs.108).aspx

    Load again your object in the controller from your DBSet and run this method. You can specify both a white list and a blacklist of parameters that shall or shall not be update.

    0 讨论(0)
  • 2020-11-28 05:34

    I made an easy way to edit properties of entities I will share with you. this code will edit Name and Family properties of entity:

        public void EditProfileInfo(ProfileInfo profileInfo)
        {
            using (var context = new TestContext())
            {
                context.EditEntity(profileInfo, TypeOfEditEntityProperty.Take, nameof(profileInfo.Name), nameof(profileInfo.Family));
            }
        }
    

    And this code will ignore to edit Name and Family properties of entity and it will edit another properties:

        public void EditProfileInfo(ProfileInfo profileInfo)
        {
            using (var context = new TestContext())
            {
                context.EditEntity(profileInfo, TypeOfEditEntityProperty.Ignore, nameof(profileInfo.Name), nameof(profileInfo.Family));
            }
        }
    

    Use this extension:

    public static void EditEntity<TEntity>(this DbContext context, TEntity entity, TypeOfEditEntityProperty typeOfEditEntityProperty, params string[] properties)
       where TEntity : class
    {
        var find = context.Set<TEntity>().Find(entity.GetType().GetProperty("Id").GetValue(entity, null));
        if (find == null)
            throw new Exception("id not found in database");
        if (typeOfEditEntityProperty == TypeOfEditEntityProperty.Ignore)
        {
            foreach (var item in entity.GetType().GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.GetProperty))
            {
                if (!item.CanRead || !item.CanWrite)
                    continue;
                if (properties.Contains(item.Name))
                    continue;
                item.SetValue(find, item.GetValue(entity, null), null);
            }
        }
        else if (typeOfEditEntityProperty == TypeOfEditEntityProperty.Take)
        {
            foreach (var item in entity.GetType().GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.GetProperty))
            {
                if (!item.CanRead || !item.CanWrite)
                    continue;
                if (!properties.Contains(item.Name))
                    continue;
                item.SetValue(find, item.GetValue(entity, null), null);
            }
        }
        else
        {
            foreach (var item in entity.GetType().GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.GetProperty))
            {
                if (!item.CanRead || !item.CanWrite)
                    continue;
                item.SetValue(find, item.GetValue(entity, null), null);
            }
        }
        context.SaveChanges();
    }
    
    public enum TypeOfEditEntityProperty
    {
        Ignore,
        Take
    }
    
    0 讨论(0)
  • we can use like this

     db.Entry(model).State = EntityState.Modified;
     db.Entry(model).Property(x => x.Token).IsModified = false;
     db.SaveChanges();
    

    it will update but without Token property

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