Nested Unit of Work in Entity Framework

自古美人都是妖i 提交于 2021-02-10 18:19:51

问题


I try to implement Unit of Work pattern in my application with use of nested units of work.

I have the following interfaces:

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
}

This is almost how things happen in XPO.

Is there any chance to implement these interfaces using Entity Framework, suppose version 4, with little pain?

I use auto-generated entity objects, not POCO.


回答1:


Not exactly your way, because I'm using POCO with state flags, but it can be applied to generated entities as well. This is a recursive approach to manage the state of the parent entity and children entities. This is the state manager class for the Parent entity:

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);
        }
    }
}

And this is the state manager for the Child entity:

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 is a simple interface which only has ChangeState method. If the Child entity had a GrandChild collection, the ChildStateManager.SetRelationsState() method would call the GrandChildStateManager.ChangeState() and so on. It's a bit complicated, but it works for me and I generate the state manager code using T4 templates.



来源:https://stackoverflow.com/questions/10672744/nested-unit-of-work-in-entity-framework

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!