实体框架和存储库模式

问题描述:

我想使用实体框架来保存域实体。我的项目的设置如下: -实体框架和存储库模式

  • UI:MVC(使用Automapper域实体和视图模型之间的映射)
  • 域名:entites的,服务,存储库接口
  • 库:实体框架(实施来自域层的接口)。使用Automapper在域实体和实体框架对象之间进行映射。

这很好,除非在我的服务中,如果我通过检查存储库来验证项目,然后执行更新。这失败了,因为实体框架标识映射已经看过该项目,我尝试重新附加它。

我可以使用代码如下(这将是更加通用)

 public void Update(Domain.Entities.Book entity) 
    { 
     Book newBook = _mapper.Map<Domain.Entities.Book, Book>(entity); 
     ObjectStateEntry cacheEntry; 
     if (_dataContext.ObjectStateManager.TryGetObjectStateEntry(_dataContext.CreateEntityKey("Books",newBook), out cacheEntry)) 
     { 
      _dataContext.Books.ApplyCurrentValues(newBook); 
     } 
     else 
     { 
      _dataContext.Books.Attach(newBook); 
      _dataContext.ObjectStateManager.ChangeObjectState(newBook, EntityState.Modified); 
     } 
     _dataContext.SaveChanges(); 
    } 

的问题是,我觉得有写同一类的代码删除

 public void Delete(Domain.Entities.Book entity) 
    { 
     Book newBook = _mapper.Map<Domain.Entities.Book, Book>(entity); 
     ObjectStateEntry cacheEntry; 
     if (_dataContext.ObjectStateManager.TryGetObjectStateEntry(_dataContext.CreateEntityKey("Books", newBook), out cacheEntry)) 
     { 
      _dataContext.ObjectStateManager.ChangeObjectState(cacheEntry.Entity, EntityState.Deleted); 

     } 
     else 
     { 
      _dataContext.Books.Attach(newBook); 
      _dataContext.ObjectStateManager.ChangeObjectState(newBook, EntityState.Deleted); 
     } 
     _dataContext.SaveChanges(); 
    } 
我自己解决此问题

我确定必须有更好的方式来实现我想要做的事情,但是我不能为我的生活找出什么!

有关上述方法的任何其他一般性评论将被赞赏,因为我即将在大型项目中使用它!

感谢

罗斯

+1

我想知道如何进入一个你不知道一个实体是否已经连接的情况。在像更新实体这样的基本用例中使用像TryGetObjectStateEntry这样的高级方法在我看来是代码味道。另外请注意,您的更新依赖于'cacheEntry.Entity'代表数据库中的原始状态,否则“ApplyCurrentValues”和更改跟踪将不会标记正确的属性被修改为执行正确的数据库更新。你是否知道,当你甚至不知道这个实体是否已经连接? – Slauma 2012-08-15 17:13:46

+0

创建资源库对象并获取项目会导致项目被加载到EF中,然后转换为域项目。然后可以编辑该域项目,然后过去到存储库更新方法。然后这个域对象(使用AutoMap)变成一个分离的EF对象。由于密钥已被保存,因此将其附加到EF将导致异常。我很惊讶这对人们来说不是一个更大的问题? – 2012-08-15 17:17:53

+0

我明白了。但是,为什么区分“域实体”和“EF实体”?没有中间映射,ORM是否能够坚持域实体? – Slauma 2012-08-15 17:44:14

除非我完全误解了你的问题,我觉得你的问题是DatabaseContext对象的多个实例。如果你从一个上下文实例中获得一个对象,然后尝试在不同的上下文实例中使用它,你将会得到很多异常:第二个上下文实例会看到对象已经连接,但是它不能使用它,导致它被附加到不同的上下文实例。

如果你只有一个上下文实例管理你的附加对象,它会看到已经附加的对象,并且只能使用它。而且,您不需要使用AutoMapper(通过成员智能克隆的方式进行高级技巧)将对象克隆到新实例以及任何其他可怕的“TryingToAttachObject”东西中。

我有很多与多个上下文实例相似的问题,直到我发现依赖注入和它的魔力:它会创建一个DBContext实例,并将它用于所有请求和EF管理。

+0

嗨,因为我刚刚回复BigDaddy上下文只有一个实例,这并不解决它我害怕。 – 2012-09-02 09:27:30

像trailmax说的,它看起来像你有多个数据上下文。我会拍摄一个数据上下文。这可以通过创建一个通用存储库来完成。假设您在实体和存储库之间有1:1的关系,本文可能会帮助您实现目标:http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application

+0

我只有1个上下文。在我的测试用户界面应用程序中,我创建了一个存储库,并将其传递给服务。这不幸的是不是问题。 – 2012-09-02 09:26:34