Exclude Property on Update in Entity Framework

Exclude Property on Update in Entity Framework

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

Exclude property from updating when SaveChanges() is called

The following may work works.

myDbContext.Dogs.Attach(dog);
myDbContext.Entry(dog).State = EntityState.Modified;

var objectContext = ((IObjectContextAdapter) myDbContext).ObjectContext;
foreach (var entry in objectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Modified).Where(entity => entity.Entity.GetType() == typeof(Dogs)))
{
// You need to give Foreign Key Property name
// instead of Navigation Property name
entry.RejectPropertyChanges("OwnerID");

}

myDbContext.SaveChanges();

If you want to do it in a single line, use the following extension method:

public static void DontUpdateProperty<TEntity>(this DbContext context, string propertyName)
{
var objectContext = ((IObjectContextAdapter) context).ObjectContext;
foreach (var entry in objectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Modified).Where(entity => entity.Entity.GetType() == typeof(TEntity)))
{
entry.RejectPropertyChanges(propertyName);
}
}

And use it like this

// After you modify some POCOs
myDbContext.DontUpdateProperty<Dogs>("OwnerID");
myDbContext.SaveChanges();

As you can see, you can modify this solution to fit your needs, e.g. use string[] properties instead of string propertyName as the argument.


Suggested Approach

A better solution would be to use an Attribute as you suggested ([NeverUpdate]). To make it work, you need to use SavingChanges event (check my blog):

void ObjectContext_SavingChanges(object sender, System.Data.Objects.SavingChangesEventArgs e)
{
ObjectContext context = sender as ObjectContext;
if(context != null)
{
foreach(ObjectStateEntry entry in context.ObjectStateManager.GetObjectStateEntries(EntityState.Modified))
{
var type = typeof(entry.Entity);
var properties = type.GetProperties();
foreach( var property in properties )
{
var attributes = property.GetCustomAttributes(typeof(NeverUpdateAttribute), false);
if(attributes.Length > 0)
entry.RejectPropertyChanges(property.Name);
}
}
}
}
// Check Microsoft documentation on how to create custom attributes:
// http://msdn.microsoft.com/en-us/library/sw480ze8(v=vs.80).aspx
public class NeverUpdateAttribute: SystemAttribute
{

}

//In your POCO
public class Dogs
{
[NeverUpdate]
public int OwnerID { get; set; }
}

Warning: I did not compile this code. I'm not at home :/


Warning 2: I have just read the MSDN documentation and it says:

ObjectStateEntry.RejectPropertyChanges Method

Rejects any changes made to the property with the given name since the
property was last loaded, attached, saved, or changes were accepted.
The orginal value of the property is stored and the property will no
longer be marked as modified.


I am not sure what its behavior would be in the case of attaching a modified entity. I will try this tomorrow.


Warning 3: I have tried it now. This solution works. Property that is rejected with RejectPropertyChanges() method are not updated in the persistence unit (database).

HOWEVER, if the entity that is updated is attached by calling Attach(), the current context remains dirty after SaveChanges(). Assume that the following row exists in the database:

Dogs
ID: 1
Name: Max
OwnerID: 1

Consider the following code:

var myDog = new Dogs();
myDog.ID = 1;
myDog.Name = Achilles;
myDog.OwnerID = 2;

myDbContext.Dogs.Attach(myDog);
myDbContext.Entry(myDog).State = EntityState.Modified;
myDbContext.SaveChanges();

The current state of database after SaveChanges():

Dogs:
ID: 1
Name: Achilles
OwnerID: 1

The current state of myDbContext after SaveChanges():

var ownerId = myDog.OwnerID;  // it is 2
var status = myDbContext.Entry(myDog).State; // it is Unchanged

So what you should do? Detach it after SaveChanges():

Dogs myDog = new Dogs();
//Set properties
...
myDbContext.Dogs.Attach(myDog);
myDbContext.Entry(myDog).State = EntityState.Modified;
myDbContext.SaveChanges();
myDbContext.Entry(myDog).State = EntityState.Detached;

How to ignore properties in Entity Framework 6 for Update?

If you are trying to ignore properties in an entity, then you would need to add a [NotMapped] attribute to that property in the class. More documentation here: https://learn.microsoft.com/en-us/ef/core/modeling/included-properties

Also, it seems like the error presented is more to do with you attempting modify a Primary key or index. I see this is actually answered here: https://stackoverflow.com/a/12397981/1670574

Ignore one property on update Entity Framework

Personally, I use AutoMapper and use Ignore on the one field you don't want to copy. This way, if you ever add new columns to the table, you don't have to worry about adding them to your repository.

So, something like this...

void UpdatePerson(Person p) {
var person = db.Persons.Find(PersonId);

Mapper.CreateMap<Person, Person>()
.ForMember(dest => dest.CreationDate, opt => opt.Ignore());
Mapper.Map(p, person);

db.SaveChanges();
}

Update an entity using entity framework while ignoring some properties

If your using EF 5, you can mark a property as not modified after its been marked as modified

_db.Entry(candidat).State = EntityState.Modified;
// Ignore changes to the value of SomeProperty
_db.Entry(candidat).Property("SomeProperty").IsModified = false;
_db.SaveChanges();

EntityFramework Exclude Some Fields in Updating and Inserting

Insert

Use [DatabaseGenerated(DatabaseGeneratedOption.Computed)] data annotation on DateCreated column to use default value generated by the database.

https://msdn.microsoft.com/en-us/data/jj591583.aspx#DatabaseGenerated

Update

Entity Framework only update modified field, so simply don't change the value of UserCreated and it will not be updated.

EF Core: Ignore property only on save

You have to set both BeforeSaveBehavior (for insert) and AfterSaveBehavior (for update) of the entity property to Ignore.

Currently there is no fluent API for that, but you could use the metadata API, e.g.

modelBuilder.Entity<Blog>().Property(e => e.ViewProp1)
.Metadata.SetBeforeSaveBehavior(PropertySaveBehavior.Ignore);
modelBuilder.Entity<Blog>().Property(e => e.ViewProp1)
.Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Ignore);


Related Topics



Leave a reply



Submit