微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

假设我们有一个具有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;
        }
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐