使用View-Models与Repository模式 [英] Using View-Models with Repository pattern

查看:165
本文介绍了使用View-Models与Repository模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 (在应用程序级别)可能有所帮助。



您应该使您的存储库仅依赖于实体,并且只保留简单的检索方法 - 也就是说,GetOrderById() - 在您的资料库(连同创建/更新/合并/删除,当然)。想象一下,实体,存储库,域服务,用户界面命令,处理这些命令的应用程序服务(例如,Web应用程序中处理POST请求的某个Web控制器等)代表您的写入



然后构建一个单独的阅读模型可以像你所希望的那样脏 - 放在这5个表的连接中,从文件中读取宇宙中的星星数的代码将它与以A开头的书数(在对Amazon进行查询之后)乘以建立一个n维结构等等 - 你得到的想法:)但是,在阅读模型,不要添加任何处理修改实体的代码。您可以从此读取模型中自由返回所需的任何View-Models,但是请从此处触发任何数据更改。



读写分离应降低程序的复杂性,使所有内容更易于管理。你也可能会看到,它不会打破你在你的问题(希望)中提到的设计规则。



从性能的角度来看,使用读取模型,即写入写入/更改数据的代码分开读取数据的代码尽可能最好,你可以得到:)是因为你甚至可以在一些没有在晚上睡觉的情况下处理一些SQL代码 - 而SQL查询(如果写得好)会给你的应用程序提供相当的速度。



Nota bene :我正在开玩笑一点,你可以如何编码你的阅读方面 - 阅读方面的代码应该像清洁那样简单,就像写入代码一样简单:)



此外,如果需要,您可以摆脱通用存储库接口,因为它只是混淆了您正在建模的域,并强制每个具体的存储库公开方法这不是必需的:)请参见。例如,很可能Delete()方法永远不会用于 OrderRepository ,因为也许订单不应该被删除(当然,一如往常)。当然,您可以将数据库行管理原语保留在单个模块中,并在您的具体存储库中重新使用这些原语,但不要将这些原语暴露给其他任何人,而是将其存储库的实现 - 仅仅因为他们不需要其他任何地方,如果公开曝光,可能会混淆一个醉酒的程序员。



最后,也许不要考虑域应用层数据层查看模型图层。请阅读此。根据其真实意义/目的(或功能)打包软件模块)比基于不自然的,难以理解的,,难以解释到5岁的孩子标准,即按层打包


I'm using Domain driven N-layered application architecture with EF code first in my recent project, I defined my Repository contracts, In Domain layer. A basic contract to make other Repositories less verbose:

public interface IRepository<TEntity, in TKey> where TEntity : class
{
   TEntity GetById(TKey id);
   void Create(TEntity entity);
   void Update(TEntity entity);
   void Delete(TEntity entity);
}

And specialized Repositories per each Aggregation root, e.g:

public interface IOrderRepository : IRepository<Order, int>
{
    IEnumerable<Order> FindAllOrders();
    IEnumerable<Order> Find(string text);
    //other methods that return Order aggregation root
}

As you see, all of these methods depend on Domain entities. But in some cases, an application's UI, needs some data that isn't Entity, that data may made from two or more enteritis's data(View-Models), in these cases, I define the View-Models in Application layer, because they are closely depend on an Application's needs and not to the Domain.

So, I think I have 2 way's to show data as View-Models in the UI:

  1. Leave the specialized Repository depends on Entities only, and map the results of Repositories's method to View-Models when I want to show to user(in Application Layer usually).
  2. Add some methods to my specialized Repositories that return their results as View-Models directly, and use these returned values, in Application Layer and then UI(these specialized Repositories's contracts that I call them Readonly Repository Contracts, put in Application Layer unlike the other Repositories'e contract that put in Domain).

Suppose, my UI needs a View-Model with 3 or 4 properties(from 3 or 4 big Entities). It's data could be generate with simple projection, but in case 1, because my methods could not access to View-Models, I have to fetch all the fields of all 3 or 4 tables with sometimes, huge joins, and then map the results to View-Models. But, in case 2, I could simply use projection and fill the View-Models directly.

So, I think in performance point of view, the case 2 is better than case 1. but I read that Repository should depend on Entities and not View-Models in design point of view.

Is there any better way that does not cause the Domain Layer depend on the Application layer, and also doesn't hit the performance? or is it acceptable that for reading queries, my Repositories depend on View-Models?(case2)

解决方案

Perhaps using the command-query separation (at the application level) might help a bit.

You should make your repositories dependent on entities only, and keep only the trivial retrieve method - that is, GetOrderById() - on your repository (along with create / update / merge / delete, of course). Imagine that the entities, the repositories, the domain services, the user-interface commands, the application services that handles those commands (for example, a certain web controller that handles POST requests in a web application etc.) represents your write model, the write-side of your application.

Then build a separate read model that could be as dirty as you wish - put there the joins of 5 tables, the code that reads from a file the number of stars in the Universe, multiplies it with the number of books starting with A (after doing a query against Amazon) and builds up a n-dimensional structure that etc. - you get the idea :) But, on the read-model, do not add any code that deals with modifying your entities. You are free to return any View-Models you want from this read model, but do trigger any data changes from here.

The separation of reads and writes should decrease the complexity of the program and make everything a bit more manageable. And you may also see that it won't break the design rules you have mentioned in your question (hopefully).

From a performance point of view, using a read model, that is, writing the code that reads data separately from the code that writes / changes data is as best as you can get :) This is because you can even mangle some SQL code there without sleeping bad at night - and SQL queries, if written well, will give your application a considerable speed boost.

Nota bene: I was joking a bit on what and how you can code your read side - the read-side code should be as clean and simple as the write-side code, of course :)

Furthermore, you may get rid of the generic repository interface if you want, as it just clutters the domain you are modeling and forces every concrete repository to expose methods that are not necessary :) See this. For example, it is highly probable that the Delete() method would never be used for the OrderRepository - as, perhaps, Orders should never be deleted (of course, as always, it depends). Of course you can keep the database-row-managing primitives in a single module and reuse those primitives in your concrete repositories, but to not expose those primitives to anyone else but the implementation of the repositories - simply because they are not needed anywhere else and may confuse a drunk programmer if publicly exposed.

Finally, perhaps it would be also beneficial to not think about Domain Layer, Application Layer, Data Layer or View Models Layer in a too strict manner. Please read this. Packaging your software modules by their real-world meaning / purpose (or feature) is a bit better than packaging them based on an unnatural, hard-to-understand, hard-to-explain-to-a-5-old-kid criterion, that is, packaging them by layer.

这篇关于使用View-Models与Repository模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆