实体框架和存储库模式
我想使用实体框架来保存域实体。我的项目的设置如下: -实体框架和存储库模式
- 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();
}
我自己解决此问题
我确定必须有更好的方式来实现我想要做的事情,但是我不能为我的生活找出什么!
有关上述方法的任何其他一般性评论将被赞赏,因为我即将在大型项目中使用它!
感谢
罗斯
除非我完全误解了你的问题,我觉得你的问题是DatabaseContext对象的多个实例。如果你从一个上下文实例中获得一个对象,然后尝试在不同的上下文实例中使用它,你将会得到很多异常:第二个上下文实例会看到对象已经连接,但是它不能使用它,导致它被附加到不同的上下文实例。
如果你只有一个上下文实例管理你的附加对象,它会看到已经附加的对象,并且只能使用它。而且,您不需要使用AutoMapper(通过成员智能克隆的方式进行高级技巧)将对象克隆到新实例以及任何其他可怕的“TryingToAttachObject”东西中。
我有很多与多个上下文实例相似的问题,直到我发现依赖注入和它的魔力:它会创建一个DBContext实例,并将它用于所有请求和EF管理。
嗨,因为我刚刚回复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。
我只有1个上下文。在我的测试用户界面应用程序中,我创建了一个存储库,并将其传递给服务。这不幸的是不是问题。 – 2012-09-02 09:26:34
我想知道如何进入一个你不知道一个实体是否已经连接的情况。在像更新实体这样的基本用例中使用像TryGetObjectStateEntry这样的高级方法在我看来是代码味道。另外请注意,您的更新依赖于'cacheEntry.Entity'代表数据库中的原始状态,否则“ApplyCurrentValues”和更改跟踪将不会标记正确的属性被修改为执行正确的数据库更新。你是否知道,当你甚至不知道这个实体是否已经连接? – Slauma 2012-08-15 17:13:46
创建资源库对象并获取项目会导致项目被加载到EF中,然后转换为域项目。然后可以编辑该域项目,然后过去到存储库更新方法。然后这个域对象(使用AutoMap)变成一个分离的EF对象。由于密钥已被保存,因此将其附加到EF将导致异常。我很惊讶这对人们来说不是一个更大的问题? – 2012-08-15 17:17:53
我明白了。但是,为什么区分“域实体”和“EF实体”?没有中间映射,ORM是否能够坚持域实体? – Slauma 2012-08-15 17:44:14