Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Entity framework 实体框架和存储库模式_Entity Framework - Fatal编程技术网

Entity framework 实体框架和存储库模式

Entity framework 实体框架和存储库模式,entity-framework,Entity Framework,我想使用实体框架来持久化域实体。我的项目设置如下:- UI:MVC(使用Automapper在域实体和视图模型之间映射) 域:实体、服务、存储库接口 存储库:实体框架(从域层实现接口)。使用Automapper在域实体和实体框架对象之间进行映射 这很有效,除非在我的服务中,我通过检查存储库来验证项目,然后执行更新。这失败了,因为EntityFrameworksIdentityMap以前见过该项,我尝试再次附加它 我可以使用如下代码解决这个问题(这将变得更通用) 公共作废更新(Domain.E

我想使用实体框架来持久化域实体。我的项目设置如下:-

  • UI:MVC(使用Automapper在域实体和视图模型之间映射)
  • 域:实体、服务、存储库接口
  • 存储库:实体框架(从域层实现接口)。使用Automapper在域实体和实体框架对象之间进行映射
这很有效,除非在我的服务中,我通过检查存储库来验证项目,然后执行更新。这失败了,因为EntityFrameworksIdentityMap以前见过该项,我尝试再次附加它

我可以使用如下代码解决这个问题(这将变得更通用)

公共作废更新(Domain.Entities.Book entity)
{
Book newBook=\u mapper.Map(实体);
ObjectStateEntry缓存条目;
if(_dataContext.ObjectStateManager.TryGetObjectStateEntry(_dataContext.CreateEntityKey(“Books”,newBook),out cacheEntry))
{
_dataContext.Books.ApplyCurrentValues(newBook);
}
其他的
{
_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();
    }
public void Delete(Domain.Entities.Book entity)
{
Book newBook=\u mapper.Map(实体);
ObjectStateEntry缓存条目;
if(_dataContext.ObjectStateManager.TryGetObjectStateEntry(_dataContext.CreateEntityKey(“Books”,newBook),out cacheEntry))
{
_dataContext.ObjectStateManager.ChangeObjectState(cacheEntry.Entity,EntityState.Deleted);
}
其他的
{
_dataContext.Books.Attach(newBook);
_dataContext.ObjectStateManager.ChangeObjectState(newBook,EntityState.Deleted);
}
_dataContext.SaveChanges();
}
我相信一定有更好的方法来实现我想做的事情,但我一辈子都搞不清楚是什么

如果您对上述方法有任何其他一般性意见,我将不胜感激,因为我将在大型项目中使用它

谢谢


Ross

除非我完全误解了你的问题,否则我认为你的问题是DatabaseContext对象的多个实例。如果您从一个上下文实例获取一个对象,然后尝试在不同的上下文实例中使用它,您将得到许多异常:第二个上下文实例将看到该对象已附加,但它无法使用它,因为它已附加到不同的上下文实例

如果只有一个上下文实例管理连接的对象,那么它将看到已连接的对象,并且只处理该对象。而且,您不需要使用AutoMapper将对象克隆到一个新实例和任何其他可怕的“TryingToAttachObject”内容中(对于成员级克隆来说,这是一种很好的技术!)


在我发现依赖注入之前,我在多个上下文实例中遇到了很多类似的问题,这很神奇:它将创建一个DBContext实例,并将其用于所有请求和EF管理。

正如trailmax所说,看起来您有多个数据上下文。我会争取一个数据上下文。这可以通过创建一个通用存储库来实现。假设您在实体和存储库之间有1:1的关系,本文可能会帮助您实现目标:。

我想知道您如何会遇到这样一种情况,即您不知道实体是否已连接。在我看来,在更新实体等基本用例中使用高级方法(如
TryGetObjectStateEntry
)是一种代码味道。还要注意,您的更新依赖于假设
cacheEntry.Entity
表示数据库中的原始状态,否则
ApplyCurrentValues
和更改跟踪不会将正确的属性标记为已修改以执行正确的数据库更新。您是否知道,当您甚至不知道实体是否已连接时,总是会发生这种情况?创建存储库对象并获取项目会导致项目加载到EF中,然后转换为域项目。然后可以编辑此域项,然后将其传递给存储库更新方法。然后(使用AutoMap)将该域对象转换为分离的EF对象。将此项附加到EF将导致异常,因为密钥已保存。我很惊讶这对人们来说不是一个更大的问题?我明白了。但为什么要区分“域实体”和“EF实体”?ORM不是要在没有中间映射的情况下持久化域实体吗?它们可以做到,但存储库模式的要点(我想!)是我可以将其切换到不同的实现。如果microsoft stop支持EF,那么我可以使用不同的ORM。如果您的EF实体来自
EntityObject
类,那么您是对的,它们不是POCO,并且直接依赖EF。但是,您可以将POCO与EF一起使用,也就是说,实体类不是从任何特定于EF的东西派生的(只是google的“实体框架POCO”或类似的东西)。EF团队不鼓励使用
EntityObject
,并建议使用POCO。您知道您正在使用的
DbContext
ObjectContext
相比吗?我还建议您熟悉它,因为它在许多方面简化了EF的使用。在我的测试UI应用程序中,我创建了一个存储库,并将其传递给服务。不幸的是,这不是问题所在。嗨,我刚刚回复了Bigdady,这里只有一个上下文实例,恐怕这不能解决问题。
        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();
    }