简体   繁体   English

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

[英]Reusable model in repository pattern

I've recently come across the problem of having multiple database types which should be swappable. 我最近遇到了具有多个应该可交换的数据库类型的问题。 My solution for this would be the repository pattern. 我的解决方案是存储库模式。 Having models like these. 拥有这样的模型。

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; }
}

Having these two classes as my model. 将这两个类作为我的模型。 And the following method in my repository. 以及我的存储库中的以下方法。

class AuthorRepository {
    IEnumerable<Author> GetAll() {
        return Context.Set<Author>().ToList();
    }
}

Now I've got a few problems. 现在我遇到了一些问题。 First would be that using the repository like this. 首先是使用像这样的存储库。

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

If I were to try and access the books inside the author model I would get a ObjectDisposedException. 如果我尝试访问作者模型中的书籍,我会得到一个ObjectDisposedException。 Which is obvious since books can only be accessed inside of the DbContext so the property should really only be used inside of the repository and not outside. 这是显而易见的,因为书籍只能在DbContext中访问,因此该属性实际上只应在存储库内使用,而不是在外部使用。

Now my second issue is that when I want to change from entity framework to another persistence framework the virtual methods would not work since (again as far as I am aware) this is only used in entity framework. 现在我的第二个问题是,当我想从实体框架更改为另一个持久性框架时,虚拟方法将无法工作(因为据我所知),这仅用于实体框架。

The setup shown above is how I've seen the repository pattern implemented just about everywhere, but I don't see the use in the pattern when I need to change my model whenever I want to change the persistence framework. 上面显示的设置是我如何看到几乎无处不在的实现的存储库模式,但是当我需要在需要更改持久性框架时需要更改模型时,我看不到模式中的用法。

My fix would be the following. 我的解决方法如下。

class Author {
    public string Name { get; set; }
}
class EntityFrameworkAuthor : Author {
    public virtual ICollection<Book> Books { get; set; }
}

The EF author would only be used in the repositories and the Author would be returned to the business layer. EF作者只会在存储库中使用,而Author将返回到业务层。

Now to my questions. 现在回答我的问题。

  1. Is the method shown above the right way to use the repository pattern if I want to be able to switch frameworks easily (which I assumed the repository pattern was for). 如果我希望能够轻松切换框架(我认为存储库模式适用于),上面显示的方法是使用存储库模式的正确方法。
  2. Is my fix a good way to improve my current model? 我的修复是改善现有模型的好方法吗? Or does it break the pattern in some way? 或者它是否以某种方式打破了模式?
  3. If not how would I go about making my model reusable for different persistence frameworks. 如果不是,我将如何使我的模型可重用于不同的持久性框架。

I don't think breaking your model in two is a good idea. 我认为将你的模型分成两部分并不是一个好主意。 Personally I always think in terms of having the business logic completely unaware of the persistence logic. 就个人而言,我总是认为业务逻辑完全没有意识到持久性逻辑。

You can do that via repository pattern which should be used in this way: you create the repository class with just the basic methods and then you add new methods as you need it. 您可以通过应该以这种方式使用的存储库模式来实现:只使用基本方法创建存储库类,然后根据需要添加新方法。 The reason for this is that you want each repository to be an abstraction of the mechanism used by your persistence layer to load the data. 这样做的原因是您希望每个存储库都是持久层用于加载数据的机制的抽象。 (here's a link that I found usefull about the repository pattern) (这是我发现有关存储库模式的链接

What I mean is that from the business layer point of view the method used to load, for example, "all Author that wrote a book in 1974" could be implemented within your code, as a stored procedure or everything else; 我的意思是,从业务层的角度来看,用于加载的方法,例如“1974年编写一本书的所有作者”可以在您的代码中实现,作为存储过程或其他所有内容; as long as the business object that requested that set of data gets what it wants, it doesn't (and shouldn't) care. 只要请求该组数据的业务对象获得它想要的东西,它就不会(也不应该)关心。

With your solution however, you're making domain objects aware of the way data are accessed. 但是,使用您的解决方案,您可以使域对象了解数据的访问方式。 Personally, if the need is to be able to change ORM in the future, I would prefer to have something like a FacadeActorRepository that uses a concrete implementation EfActorRepository that you'll be able to switch as you change your ORM. 就个人而言,如果将来需要能够更改ORM,我宁愿使用FacadeActorRepository,它使用一个具体的实现EfActorRepository,您可以在更改ORM时切换。

As for the lazy loading issue, as plalx pointend out in the comments, (quote) 至于延迟加载问题,作为plalx pointend在评论中,(引用)

"If the data is not used in business logic conditions to protect the state of the aggregate (data cluster) to which it belongs and this data could exist on it's own then it shouldn't be aggregated" “如果数据未在业务逻辑条件中用于保护其所属的聚合(数据集群)的状态,并且此数据可能存在于其自身,那么它不应该被聚合”

which means that if Author really needs a list of Books, you shouldn't allow it to be lazy loaded, but you should have it as soon as the Author object is finished being created. 这意味着如果作者真的需要一个书籍列表,你不应该允许它延迟加载,但是你应该在创建完成作者对象后立即加载它。

I hope this helps :) 我希望这有帮助 :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM