保存前实体的副本(回滚目的)?

时间:2016-07-25 09:56:10

标签: c# entity-framework

作为我工作中的新手,我为一位离开公司的同事负责该项目。这是他的项目,所以这使所有的工作变得复杂,因为我对所有事情都很孤单,而且随着你的进展我学习了EF。该项目是一个客户端 - 服务器应用程序,使用EF6,UoW和存储库方法。

让我概述一下这个问题。存储库

中的服务器端有一个方法
MyEntity SaveMyEntity(MyEntity myEntity)
{
    //Do some validation before save - call stored procedure
    //If fails throw exception

    using(var context = new SomeContext())
    {
        //little bit of code for imagination how implementation looks like
        context.my_entity_context_base.Attach(myEntity);
        context.SyncObjectState(myEntity, myEntity.ObjectState);
        context.SaveChanges();

        //...

        if (myEntity.EntityB != null && myEntity.EntityB.Count > 0)
        {
            foreach (var u in myEntity.EntityB.ToList())
            {
                context.entity_b_context_base.Attach(u);
                context.SyncObjectState(u, u.ObjectState);
            }

            context.SaveChanges();
        }

        if (myEntity.EntityC != null && myEntity.EntityC.Count > 0)
        {
            foreach (var t in myEntity.EntityC.ToList())
            {
                context.entity_c_context_base.Attach(t);
                context.SyncObjectState(t, t.ObjectState);
            }

            context.SaveChanges();
        }

        // and so on ..
    }

    //Validation after save - stored procedur is called
    //If fails throws exception
    //If validate_after_save fails there is rollback on DB side.

    base.ExecuteStoredProcedure("validate_after_save", ref parameters, ref errorText);

    if (!string.IsNullOrEmpty(errorText))
    {
        throw new OwnException("Save failed: " + errorText);
    }

    return this.GetMyEtity(myEntity.id);
}

当没有异常被抛出时一切都很好但是在保存抛出之后验证时,客户端没有得到实际的实体。在我之前发现的某些情况下,这确实是个问题。例如,我想要保存实体。保存抛出ex之后的验证(因此客户端不接收实体)。所以我会改变一些东西并再次保存。因为保存之后的先前验证会引发异常,所以客户端仍然处于“已添加”状态,因此它会抛出主键违例。

所以我得到了创建相同机制的任务,这使得在EF中进行回滚。当抛出异常时,他们想要原始数据。正如您在上面的代码中看到的,现在没有类似的东西。当然,我在脑海中有交易,但是如何将它实现到您可以在上面看到的当前实现?

我的想法是从DB获取当前实体。在异常的情况下,我使用保存前获得的数据调用SaveMyEntity。但很少有问题:

  1. 我不确定在哪里存储原始数据的引用(客户端 或服务器)?
  2. 我将不得不改变原始实体的状态。
  3. 这种关系腐败的气味
  4. 我可以给你一些建议吗?

    非常感谢!

    编辑:

    我刚发现TransactionScope的存在。所以我试着做这样的事情

    void SaveMyEntity(MyEntity myEntity)
    {
        //...
    
        using (var scope = new TransactionScope(TransactionScopeOption.Required,
                new TransactionOptions { IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted }))
        {
            using(var context = new SomeContext())
            {
                //...
    
                if (myEntity.EntityB != null && myEntity.EntityB.Count > 0)
                {
                    foreach (var u in myEntity.EntityB.ToList())
                    {
                        context.entity_b_context_base.Attach(u);
                        context.SyncObjectState(u, u.ObjectState);
                    }
    
                    context.SaveChanges();
                }
    
                if (myEntity.EntityC != null && myEntity.EntityC.Count > 0)
                {
                    foreach (var t in myEntity.EntityC.ToList())
                    {
                        context.entity_c_context_base.Attach(t);
                        context.SyncObjectState(t, t.ObjectState);
                    }
    
                    context.SaveChanges();
                }
    
                // and so on ..
            }
    
            base.ExecuteStoredProcedure("validate_after_save", ref parameters, ref errorText);
    
            if (!string.IsNullOrEmpty(errorText))
            {
                //Rollback
                scope.Dispose();
                throw new OwnException("Save failed: " + errorText);
            }
            else
            {
                //Commit
                scope.Complete();
            }
        }
    }
    

    它确实很好用。但我不确定这是否是正确的解决方案。

0 个答案:

没有答案