2017-07-25 125 views
3

假设我们有一个MyDbContext其中包含DbSet<MyEntity>。我试图实施以下情形(因为我发现它被称为断开连接的情况下或断开模式):从数据库如何仅通过EntityFramework更新实体的已更改属性

  1. 我获得List<MyEntity>(它可以通过一些过滤条件可以简单地通过全部或DbContext.MyEntities.ToList()记录记录 - 没关系)。
  2. 然后,这些实体被传递给用户可以更改属性的某个用户界面。他的行为是不可预测的:他可以改变每个实体的每一个属性,或者他只能改变一个实体的一个属性(他甚至可以根本不改变)。
  3. 之后,我需要将更新传递给数据库。

为了执行这一方案,我发现我买两个可能的解决方案:

1)整个场景中保持连接打开。所以它会这样工作:

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(); 

但是在这个解决方案中,数据库连接持续时间过长。 UI工作时不应该打开(例如,用户可以在几个小时内更改实体)。

2)获取List<MyEntity>后关闭连接,并在将更新传递到数据库时再次打开 连接。所以它会工作 是这样的:

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(); 

但在这个解决方案,我认为这绝对是所有的entites的所有属性进行了修改。它会导致巨大的数据库更新开销。

另一种选择是编写MyEntityWrapper类,它将跟踪用户执行的所有更改并知道哪些属性需要更新。所以,我可以改变我的代码上面的这一个:

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 
} 

所以 - 有没有一些更好的解决方案,我可以不用写MyEntityWrapper类只更新更改的属性?我可以简单地告诉DbContext:“这里是一些List<MyEntity> - 拿它,确定哪些属性不同于数据库中的值并更新这些值”?

顺便说一句。如果它的事项 - 我与SQLite数据库通过Devart dotConnect工作的SQLite + 的EntityFramework 6.0.1

回答

0

请对下面的代码一看,我认为它可以帮助你(在谷歌找到了)

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; 
     } 
    } 
} 
+0

Thx,该解决方案适用于我。顺便说一下'因为'dbEntityEntry.Property()'具有'String'参数的重载,所以''updatedProperties''可以很容易地更改为'params String [] updatedPropertiesNames'。此外,即使我更新了某些属性值,并忘记将该属性名称添加到'updatedPropertiesNames'中 - 在'else'之后的代码块像魅力一样工作(枚举所有值当然要慢得多 - 但这是一个很好的保护措施) 。 – bairog