【问题标题】:Nested Unit of Work in Entity Framework实体框架中的嵌套工作单元
【发布时间】:2012-05-20 10:45:42
【问题描述】:

我尝试在我的应用程序中实现工作单元模式使用嵌套工作单元

我有以下接口:

interface IDataService
{
  IUnitOfWork NewUnitOfWork();
  INestedUnitOfWork NewNestedUnitOfWork(IUnitOfWork parent);
}

interface IUnitOfWork : IDisposable
{
  void Commit();
}

interface INestedUnitOfWork : IUnitOfWork
{
  IUnitOfWork Parent { get; }
  object GetParentObject(object obj);   // get the same object in parent uow
  object GetNestedObject(object obj);   // get the same object in this uow
}

XPO 的情况几乎就是这样。

是否有机会使用实体框架(假设版本 4)轻松实现这些接口?

我使用自动生成的实体对象,而不是 POCO。

【问题讨论】:

  • 当您尝试使用 Entity Framework 做一些很酷的事情时,您会遇到麻烦(为什么要切换到 Lightspeed)。您需要查看当前使用 EF 的工作单元的实现,并确定如何实现嵌套。这里有一些很棒的代码code.google.com/p/ef4prs/source/browse/trunk/…
  • 好吧,我尝试了事务,但它们不会在回滚时恢复对象上下文更改。所以,我仍然无法确定如何实现嵌套。

标签: c# .net entity-framework nested unit-of-work


【解决方案1】:

不完全是你的方式,因为我使用带有状态标志的 POCO,但它也可以应用于生成的实体。这是一种管理父实体和子实体状态的递归方法。这是Parent 实体的状态管理器类:

public partial class ParentStateManager : IStateManager<Parent, MyObjContext>
{

    private IStateManager<Child, MyObjContext> _ChildStateManager = new ChildStateManager();
    public void ChangeState(Parent m, MyObjContext ctx)
    {
        if (m == null) return;
        ctx.Parents.Attach(m);
        if (m.IsDeleted)
        {
            ctx.ObjectStateManager.ChangeObjectState(m, System.Data.EntityState.Deleted);
        }
        else
        {
            if (m.IsNew)
            {
                ctx.ObjectStateManager.ChangeObjectState(m, System.Data.EntityState.Added);
            }
            else
            {
                if (m.IsDirty)
                {
                    ctx.ObjectStateManager.ChangeObjectState(m, System.Data.EntityState.Modified);
                }
            }
        }
        SetRelationsState(m, ctx);
    }
    private void SetRelationsState(Parent m, MyObjContext ctx)
    {
        foreach (Child varChild in m.Children.Where(p => !p.IsDeleted))
        {
            _ChildStateManager.ChangeState(varChild, ctx);
        }
        while (m.Children.Where(p => p.IsDeleted).Any())
        {
            _ChildStateManager.ChangeState(m.Children.Where(p => p.IsDeleted).LastOrDefault(), ctx);
        }
    }
}

这是Child 实体的状态管理器:

public partial class ChildStateManager : IStateManager<Child, MyObjContext>
{

    public void ChangeState(Child m, MyObjContext ctx)
    {
        if (m == null) return;
        ctx.Children.Attach(m);
        if (m.IsDeleted)
        {
            ctx.ObjectStateManager.ChangeObjectState(m, System.Data.EntityState.Deleted);
        }
        else
        {
            if (m.IsNew)
            {
                ctx.ObjectStateManager.ChangeObjectState(m, System.Data.EntityState.Added);
            }
            else
            {
                if (m.IsDirty)
                {
                    ctx.ObjectStateManager.ChangeObjectState(m, System.Data.EntityState.Modified);
                }
            }
        }
        SetRelationsState(m, ctx);
    }
    private void SetRelationsState(Child m, MyObjContext ctx)
    {
    }
}

IStateManager 是一个简单的接口,只有ChangeState 方法。 如果Child 实体有一个GrandChild 集合,则ChildStateManager.SetRelationsState() 方法将调用GrandChildStateManager.ChangeState() 等等。这有点复杂,但它对我有用,我使用 T4 模板生成状态管理器代码。

【讨论】:

  • @dradu:对不起,我看不出这对我有什么帮助,例如:1)在新创建的会话中选择一些 Parent 对象,2)对它的原始属性,3) 对子项进行一些更改能够取消它们,如果需要 4) 保存更改(未取消)
  • 很抱歉没有提供太多帮助。我不确定嵌套工作单元的概念。通常,您的 EF 上下文会实现一个工作单元接口。 UoW 被传递到一个或多个对相应实体执行更新的存储库。最后,如果发生任何错误,UoW 将提交更改或回滚所有内容。您说“如果要求,对能够取消它们的孩子进行一些更改”,但应该什么时候发生?
  • @dradu:想象一下我编辑复杂对象的表单。它有子对象的集合。每个子对象都有其其他对象的子集合。我想以只读模式显示子记录并以另一种形式编辑它们。我可以在我的视图模型中保存所有值的副本,但是当嵌套超过 2 级时,它变得很复杂。要求是能够取消任何级别的更改,包括对子项所做的更改。我认为嵌套方法对我有很大帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-02
  • 2011-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多