从实体内部使用UnitOfWork是否可以接受

时间:2014-01-12 01:01:31

标签: c# design-patterns ef-code-first entity-framework-5 unit-of-work

我自己一直在使用单独的项目为我的数据访问层开发一个ASP.NET MVC4项目。我正在使用Entity Framework 5 Code First工作流,我已经实现了我认为非常标准Repository patternUint Of Work来将数据层与业务逻辑分开。

一切都按预期工作,我已经有很多业务逻辑,但我没有太多的经验(总共大约9个月),现在一个非常有经验的开发人员正在加入该项目,突然我开始得到这个错误:

  

无法定义两个对象之间的关系,因为   它们附加到不同的ObjectContext对象。

我的项目结构就是这个 -

Solution screenshot

只是我UnitOfWork课程的一部分:

 public class UnitOfWork : IDisposable
{
    private MyDbContext context = new MyDbContext ();

    private MenuRepository мenuRepository;
    public MenuRepository MenuRepository
    {
        get
        {
            if (this.мenuRepository == null)
                this.мenuRepository = new MenuRepository(context);
            return мenuRepository;
        }
    }

    //register other repositories...
}

我的存储库具有标准外观:

 public class MenuRepository : GenericRepository<Menu>, IMenuRepository
 {
     public MenuRepository(MyDbContext context) : base(context) { }
 }

我知道这还不足以判断实施是否足够好但是它已经工作了几个月而没有注意到任何问题。今天我实现了一个用子菜单编辑菜单的逻辑:

Menu menu = unitOfWork.MenuRepository.GetById(model.MenuID);
    long menuItemId = menu.MenuItems[0].MenuItemID;
    if (menu != null)
    {
      menu.Name = model.MenuName;
      MenuItem menuItem = unitOfWork.MenuItemRepository.GetById(menuItemId);
      menuItem.Name = "Test";

      unitOfWork.MenuRepository.Update(menu);

      return View(model);
    }

这一切都发生在我的控制器里,我有这个:

private UnitOfWork unitOfWork = new UnitOfWork();

因此,当我尝试执行此代码时,我从上面得到了..attached to different ObjectContext objects.的错误。

我在代码开始崩溃之前注意到的唯一变化是从另一个人直接添加到Menu实体:

//private DAL.UnitOfWork.UnitOfWork unitOfWork = new DAL.UnitOfWork.UnitOfWork();
    public Menu()
    {
        MenuItems = new List<MenuItem>();
    }

    public int MenuID { get; set; }
    //private int menuId;
    //public int MenuID {
    //    get
    //    {
    //        return menuId;
    //    }
    //    set
    //    {
    //        menuId = value;
    //        if (MenuItems.Count == 0)
    //        {
    //            MenuItems = unitOfWork.MenuItemRepository.GetBy(x => x.MenuID == menuId).ToList();
    //        }
    //    }
    //}

在我评论了上述所有内容之后,将其返回到public int MenuID { get; set; }而没有其他逻辑,删除数据库并重新创建它我能够继续使用控制器中的Update逻辑而不会出现错误对于不同的对象上下文。

所以我的问题是 - 直接从可接受的实体使用UnitOfWork。我已经实现了Data Access Layer,但我已经使用了不同文章中的大量信息,我不能说我完全理解一切背后的原因。但是在我看来,以这种方式使用它不仅会导致代码崩溃,而且还违背了使用RepositoriesUnitOfWork来管理数据的整个想法。另一方面,添加此代码的人有超过10年的编程经验,所以我不能告诉他必须更改他的代码。所以实际上可以在实体内部使用unitOfWork,如上例所示,如果它实际上是,那么如何解决使用不同对象上下文的错误?

1 个答案:

答案 0 :(得分:2)

在我看来(这不一定有效,我的ASP经验很少),在这种情况下,实体肯定不应该使用UnitOfWork,或者甚至不知道它。

如果您已经配置了实体框架正在管理的Menu个实体,并且您有几个现有的存储库设置为进一步抽象&amp;管理您的数据库交互,污染您的模型没有意义。

我假设错误正在出现,因为另一个开发人员在模型中定义的新UnitOfWork是一个新的上下文,而Menu实体已经从另一个上下文中获取(您的{ {1}}),你已经想到了。

在设置MenuID时,如果MenuRepository实体中没有任何存在,则其他开发人员似乎正在尝试加载子MenuItems。我不完全清楚那里发生了什么,似乎他们期望该项目的ID被更改,然后想要获得Menu属于MenuItems的新ID(我不确定你为什么要更改ID。

使用MenuMenuItem或{{1>,在检索实体时或之后的Lazy加载应该是可能的,具体取决于实体的映射/配置方式加载。

当然值得与其他开发人员交谈并找出他们想要实现的目标,不要担心某人拥有(或说他们拥有)的经验,这些概念中的许多可能对他们来说都是新的同样,或者他们可能花了所有时间来强化坏习惯,优秀的程序员应该总是愿意讨论各种方法。

有关加载的一些额外信息:http://msdn.microsoft.com/en-us/data/jj574232.aspx