使用视图的模型与存储库模式 [英] Using View-Models with Repository pattern

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

问题描述

我使用的领域驱动的N-分层应用架构 EF代码首先在我最近的项目,我定义我的的合同,在层。
基本合同让其他更简洁:

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
}



正如你所看到的其他方法,所有这些方法依赖于域实体
,而在某些情况下,应用程序的 UI ,需要一些数据,是不是实体,该数据可以从两个或多个肠炎的数据所做的(视图模型 S),在这种情况下,我定义了视图模型应用程序S层,因为它们是密切依赖于一个应用程序的需要,而不是在

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.

所以,我觉得我有2路的显示数据为查看 - 型号 UI

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


  1. 将专门 只依赖于实体和的方法的结果映射查看 - 型号时,我想展现给用户(在应用层通常情况下)。

  2. 添加了一些方法,返回他们的结果为查看 - 型号直接我的专业,并使用这些返回的值,在应用层然后 UI (这些专门的合同,我给他们打电话只读存储库合约 S,放在应用层不像其他)>库电子合同。

  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).

假设,我的 UI 需要视图模型 3或4个属性(3或4 实体)。
它的数据可以用简单的投影生成,但万一1,因为我的方法不能访问查看 - 型号,我为获取所有所有3个或4个表中的字段有有时,硕大的连接,然后将结果为查看 - 型号映射。
,而在第二种情况下,我可以简单地使用投影,并填写视图模型取值直接。

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.

所以,我觉得在性能上来看,本案2比1的情况下更好,但我读应取决于实体,而不是查看 - 型号在设计的角度来看。

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.

有没有更好的办法这不会导致图层取决于应用层上,也不会碰到的表现?还是可以接受的,对于阅读查询,我的取决于查看 - 型号?(情形2)

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.

您应该让您的存储库依赖于实体而已,只保留的琐碎的检索方法 - 即 GetOrderById()的 - 在你的资料库(与创建/更新/合并/删除,当然)。试想一下,在实体存储库,域名服务,用户界面的命令,处理这些命令的应用服务(例如,在Web应用程序等处理POST请求一定的网络控制器),代表您的写模型写端应用程序的

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.

然后建立一个独立的阅读模式的可能是因为脏如你所愿 - 放在那里的加入5表,从文件中读取的恒星在宇宙中的码,与以A开头的图书数量相乘(做对亚马逊查询后),建立了一个N维的结构,等等 - 你的想法:)但是,在读模式,不添加与修改您的实体交易的任何代码。你可以自由返回你从这个模型读取想要的任何视图的模型,但不要从这里触发任何数据变化。

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).

从性能的角度来看,使用的阅读模式,也就是编写的数据的代码>写入/修改数据是最好的,你可以得到:)这是因为你甚至可以有裂伤一些SQL代码,而晚上睡觉不好 - 和SQL查询,如果写的不好,会给你的应用程序相当的速度提升

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 :)

此外,你可以摆脱的通用库的接口,如果你想要的,因为它只是杂波您正在建模和域迫使每一个具体的存储库,以公开方法这是没有必要的:)请参见这个。例如,它是极有可能的删除()方法将永远不会被用于 OrderRepository 的 - 如,或许,订单应该永远不会被删除(当然,一如既往,这取决于)。当然,你可以保留的数据库行管理的单一模块中的原语和您的具体资料库重用这些原语,但没有公开这些原语给任何人,但库的实现 - 仅仅是因为他们不需要其他任何地方,并可能会混淆如果公开曝光醉程序员。

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.

最后,也许这将是还没有想到的领域层应用层数据层的或的视图模型层的一个过于严格的方式。请阅读这一点。通过他们的真实世界的意义/目的打包的软件模块(或特征 )是有点比它们打包基于一个更好的自然很难理解难以解释到A-5-旧式孩子的准则,那就是一层包装他们的

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.

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

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