如何在EF 6场景中避免不必要的并发异常?

时间:2014-04-14 16:36:35

标签: c# concurrency entity-framework-6 n-tier-architecture

我正在使用EF 6.我有一个使用WCF Soap和DTO传输数据的双层应用程序。我通过网络发送一个对象图供用户更新,然后将其发回以保留更改。在此期间,我使用AutoMapper与DTO和实体进行转换。

在持久性方面,我收到了我的DTO并将其解压缩(它包含实体列表)。我将它解压缩到适当的实体中并通过检查id是否为0来检查我们是否正在添加或编辑。到目前为止,我只是盲目地更新了id> gt的每个实体。 0

但是,我已经了解到这不是最好的方法,因为它会抛出不必要的并发异常。如果我只是在实体上调用update,则即使没有字段实际更改数据库中的值,rowversion也会更新。这导致不必要的并发异常。我需要避免这些。所以我需要以某种方式检查实体是否真的需要更新。我知道如何检查实体是否需要更新的唯一方法是查询数据库并通过属性检查执行属性。

我的问题:我是否走在正确的轨道上?事实上,我真的需要按属性检查实体属性,以确定是否需要更新?是否有更简单或更自动的方式?

在保存更改之前,需要为每个实体查询数据库,我感到很沮丧。也许我错过了什么?

以下是我的代码示例:

var ws = saveRequest.Workspace;
var td = saveRequest.ToDelete;

using (var db = new EngineeringContext())
{
    var ass = Attach<JobAssembly>(db, db.JobAssemblies, ws.Assemblies.ToDomain());
    var opr = Attach<JobOperation>(db, db.JobOperations, ws.Operations.ToDomain());
    var mtl = Attach<JobMaterial>(db, db.JobMaterials, ws.Materials.ToDomain());

    Delete<JobAssembly>(db, td.Assemblies.ToDomain());
    Delete<JobOperation>(db, td.Operations.ToDomain());
    Delete<JobMaterial>(db, td.Materials.ToDomain());

    try
    {
        db.SaveChanges();
    }
    catch (DbUpdateConcurrencyException ex)
    {
        throw new Exception("Sync Error: The data failed to save due to changes by another user.", ex);
    }

    ws.Assemblies = ass.ToDto();
    ws.Operations = opr.ToDto();
    ws.Materials = mtl.ToDto();
}

如果附加和删除看起来像这样:

db.Entry<T>(entity).State = EntityState.Modified; // .Deleted for deletes.

ToDomain和ToDto是将域(实体)映射到dtos和反之亦然的扩展。

0 个答案:

没有答案