Reputation: 3373
Let's say we have a MyDbContext
having DbSet<MyEntity>
in it. I'm trying to implement the following scenario (as I found out it is called disconnected scenario or disconnected mode):
List<MyEntity>
from database (it can be simply all records via DbContext.MyEntities.ToList()
or records by some filter condition - it doesn't matter).To implement that scenario I've found for me two possible solutions:
1) Keep connection open during the whole scenario. So it will work like this:
MyDbContext.Database.Connection.Open();
List<MyEntity> EntitiesList = MyDbContext.MyEntities.ToList();
//passing EntitiesList to the UI, where user can change them
EntitiesList[0].SomeStringProperty = "123";
//change some other properties here
//saving changes to database some time later
MyDbContext.SaveGhanges();
MyDbContext.Database.Connection.Close();
But in this solution database connection persists open too long. It shouldn't be open when UI is working (because user can change entities during several hours for example).
2) Close connection after obtaining List<MyEntity>
and open
connection again when passing updates to database. So it will work
like this:
MyDbContext.Database.Connection.Open();
List<MyEntity> EntitiesList = MyDbContext.MyEntities.ToList();
MyDbContext.Database.Connection.Close();
//passing EntitiesList to the UI, where user can change them
EntitiesList[0].SomeStringProperty = "123";
//change some other properties here
//saving changes to database some time later
MyDbContext.Database.Connection.Open();
foreach(var entity in EntitiesList)
{
//Attach updated entity and make context know that it is modified
MyDbContext.MyEntities.Attach(entity);
MyDbContext.MyEntities(entity).State = EntityState.Modified;
}
MyDbContext.SaveGhanges();
MyDbContext.Database.Connection.Close();
But in this solution I think that absolutely all properties of all entites were modified. It results in huge database update overhead.
Another choice will be to write MyEntityWrapper
class which will track all changes performed by user and will know which properties needs to be updated. So I can change my code above to this one:
foreach(var entity in EntitiesList)
{
//Attach updated entity and make context know which properties are modified
MyDbContext.MyEntities.Attach(entity);
MyDbContext.Entry(entity).Property(e => e.SomeStringProperty).IsModified = true;
//mark other changed properties
}
So - is there some more elegant solution, can I update only changed properties without writing MyEntityWrapper
class? Can I simply tell DbContext: "here is some List<MyEntity>
- take it, determine which properties differs from that values in a database and update those values"?
BTW. If it matters - I'm working with SQLite database via Devart dotConnect for SQLite + EntityFramework 6.0.1
Upvotes: 7
Views: 8671
Reputation: 129
Please have a look on below code, I think it may help you (Found out on Google )
public virtual void Update(T entity, params Expression<Func<T, object>>[] updatedProperties)
{
//Ensure only modified fields are updated.
var dbEntityEntry = DbContext.Entry(entity);
if (updatedProperties.Any())
{
//update explicitly mentioned properties
foreach (var property in updatedProperties)
{
dbEntityEntry.Property(property).IsModified = true;
}
}
else{
//no items mentioned, so find out the updated entries
foreach (var property in dbEntityEntry.OriginalValues.PropertyNames)
{
var original = dbEntityEntry.OriginalValues.GetValue<object>(property);
var current = dbEntityEntry.CurrentValues.GetValue<object>(property);
if (original != null && !original.Equals(current))
dbEntityEntry.Property(property).IsModified = true;
}
}
}
Upvotes: 5