Exclude Property on Update in Entity Framework
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();
@svendk updated:
And if you (as me) are wondering why model
don't have the token either before or after db.SaveChanges(), it's because with Update, the entity is actually not retrieved - only an SQL Update clause is sent - so the context don't know of your model
's preexisting data, only the information you gave it in db.Update(mode)
. Even if you Find(model.id)
you are not getting your context updated, as there is already loaded a model
in the context, it is still not retrieved from database.
If you (as me) wanted to return the finished model as it looks like in the database, you can do something like this:
db.Update(model);
db.Entry(model).Property(x => x.Token).IsModified = false;
db.SaveChanges();
// New: Reload AFTER savechanges, otherwise you'll forgot the updated values
db.Entry(model).Reload();
Now model
is loaded from database with all the values, the updated and the (other) preexisting ones.
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.
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
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
}