加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 如何通过EntityFramework仅更新实体的已更改属性

发布时间:2020-12-15 22:46:01 所属栏目:百科 来源:网络整理
导读:假设我们有一个具有DbSet MyEntity的MyDbContext.在里面.我正在尝试实现以下方案(因为我发现它被称为断开连接方案或断开连接模式): 我获得了List MyEntity从数据库(它可以简单地通过DbContext.MyEntities.ToList()的所有记录或通过某些过滤条件记录 – 它没
假设我们有一个具有DbSet< MyEntity>的MyDbContext.在里面.我正在尝试实现以下方案(因为我发现它被称为断开连接方案或断开连接模式):

>我获得了List< MyEntity>从数据库(它可以简单地通过DbContext.MyEntities.ToList()的所有记录或通过某些过滤条件记录 – 它没关系).
>然后将这些实体传递给用户可以更改属性的某个UI.他的行为是不可预测的:他可以改变每个实体的每一个属性,或者他只能改变一个实体的一个属性(他甚至根本不能进行任何改变).
>之后我需要将更新传递给数据库.

为了实现这种情况,我找到了两种可能的解决方案:

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

BTW.如果重要 – 我正在通过Devart dotConnect for SQLite EntityFramework 6.0.1使用SQLite数据库

解决方法

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读