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
C# 存储库模式中的可重用模型_C#_Entity Framework_Design Patterns_Repository Pattern - Fatal编程技术网

C# 存储库模式中的可重用模型

C# 存储库模式中的可重用模型,c#,entity-framework,design-patterns,repository-pattern,C#,Entity Framework,Design Patterns,Repository Pattern,我最近遇到了多个数据库类型的问题,这些数据库类型应该是可交换的。我的解决方案是存储库模式。 有这样的模型 class Book { public string Title { get; set; } public virtual Author Author { get; set; } } class Author { public string Name { get; set; } public virtual ICollection<Book> Bo

我最近遇到了多个数据库类型的问题,这些数据库类型应该是可交换的。我的解决方案是存储库模式。 有这样的模型

class Book {
    public string Title { get; set; }
    public virtual Author Author { get; set; }
}
class Author {
    public string Name { get; set; }
    public virtual ICollection<Book> Books { get; set; }
}
教材{
公共字符串标题{get;set;}
公共虚拟作者{get;set;}
}
类作者{
公共字符串名称{get;set;}
公共虚拟ICollection图书{get;set;}
}
以这两个类作为我的模型。 以及我的存储库中的以下方法

class AuthorRepository {
    IEnumerable<Author> GetAll() {
        return Context.Set<Author>().ToList();
    }
}
class AuthorRepository{
IEnumerable GetAll(){
返回Context.Set().ToList();
}
}
现在我有几个问题。首先是像这样使用存储库

using(var unitOfWork = new UnitOfWork(new MyContext())) {
    MyObservableCollection = new ObservableCollection<Author>(unitOfWork.Authors.GetAll());
}
使用(var unitOfWork=newunitofwork(new MyContext())){
MyObservableCollection=新的ObservableCollection(unitOfWork.Authors.GetAll());
}

如果我尝试访问author模型中的书籍,我会得到一个ObjectDisposedException。这一点很明显,因为书籍只能在DbContext内部访问,所以该属性实际上只能在存储库内部使用,而不能在存储库外部使用

现在,我的第二个问题是,当我想从实体框架更改为另一个持久性框架时,虚拟方法将无法工作,因为(就我所知)这只在实体框架中使用

上面所示的设置就是我在几乎所有地方看到的存储库模式的实现方式,但是当我需要在任何时候更改持久性框架时,我看不到该模式的用途

我的解决办法如下

class Author {
    public string Name { get; set; }
}
class EntityFrameworkAuthor : Author {
    public virtual ICollection<Book> Books { get; set; }
}
类作者{
公共字符串名称{get;set;}
}
类EntityFrameworkAuthor:作者{
公共虚拟ICollection图书{get;set;}
}
EF作者将仅在存储库中使用,并且作者将返回到业务层

现在回答我的问题

  • 如果我希望能够轻松地切换框架(我假设存储库模式就是为了切换框架),那么上面显示的方法是使用存储库模式的正确方法吗
  • 我的修复是改进当前模型的好方法吗?还是在某种程度上打破了这种模式
  • 如果不是,我将如何使我的模型可用于不同的持久性框架

  • 我不认为把你的模型一分为二是个好主意。就我个人而言,我总是认为业务逻辑完全不知道持久性逻辑

    您可以通过repository模式实现这一点,该模式应该以这种方式使用:您只使用基本方法创建repository类,然后根据需要添加新方法。 原因是您希望每个存储库都是持久层加载数据所用机制的抽象。 (以下是一个我发现对存储库模式有用的示例)

    我的意思是,从业务层的角度来看,用于加载的方法,例如,“1974年写过一本书的所有作者”可以在代码中实现,作为存储过程或其他任何东西;只要请求该数据集的业务对象得到了它想要的,它就不会(也不应该)在意

    但是,通过您的解决方案,您可以让域对象了解数据的访问方式。 就个人而言,如果将来需要能够更改ORM,我更希望有一个FacadeActorRepository,它使用一个具体的实现库,您可以在更改ORM时进行切换

    至于延迟加载问题,正如评论中指出的那样,(引用)

    “如果数据未在业务逻辑条件中使用以保护 它所属的聚合(数据群集)的状态以及此 数据可以自己存在,那么不应该聚合”

    这意味着,如果Author确实需要一个图书列表,您不应该允许它被延迟加载,但应该在Author对象创建完成后立即加载它


    我希望这会有所帮助:)

    “因为书籍只能在DbContext中访问,所以属性“为什么EF不会急切地返回完全填充的作者及其书籍?”这是因为该属性是虚拟的,这允许实体框架延迟加载导航属性。@plalx这可以通过使用Include来修复,但这并不是我想要的。主要问题仍然是导航属性是特定于实体框架的,因此打破了存储库模式的抽象(在我看来)。延迟加载实体数据对我来说是一种代码味道,通常表明您的数据聚合是错误的。您应该只聚合执行业务规则事务所需的最小数据量,而不是更少,也不是更多。在这些情况下,总是急切地加载数据是有意义的。另外,不要忘记,对象对于处理命令和保护复杂域的不变量是最有用的。我不会为了查询而将数据塞进业务对象中(不过您可以使用DTO)。如果数据未在业务逻辑条件中用于保护其所属的聚合(数据集群)的状态,并且该数据可能独立存在,则不应聚合该数据。例如,一篇文章通常不应该包含注释对象的集合,即使我们总是说一篇文章有注释。这是因为通常没有适用于帖子及其所有评论的业务规则。因此,Post和Comment应该被建模为单独的聚合,并且仅由identity引用。