如何通过EntityFramework

时间:2017-07-25 05:36:07

标签: c# entity-framework sql-update

假设我们MyDbContext中有DbSet<MyEntity>。我正在尝试实现以下方案(因为我发现它被称为断开连接方案或断开连接模式):

  1. 我从数据库中获取List<MyEntity>(它可以是通过DbContext.MyEntities.ToList()的所有记录,也可以是某些过滤条件下的记录 - 无关紧要。)
  2. 然后将这些实体传递给用户可以更改属性的UI。他的行为是不可预测的:他可以改变每个实体的每一个属性,或者他只能改变一个实体的一个属性(他甚至根本不会做任何改变)。
  3. 之后我需要将更新传递给数据库。
  4. 为了实现这种情况,我找到了两种可能的解决方案:

    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> - 接受它,确定哪些属性与数据库中的值不同并更新这些值”?

    顺便说一句。如果重要 - 我正在通过 Devart dotConnect for SQLite + EntityFramework 6.0.1

    使用SQLite数据库

1 个答案:

答案 0 :(得分:1)

请查看下面的代码,我认为它可以帮助您(在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;
        }
    }
}
相关问题