首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >将视图模型与存储库模式一起使用

将视图模型与存储库模式一起使用
EN

Stack Overflow用户
提问于 2014-04-25 16:26:14
回答 3查看 9K关注 0票数 21

我在最近的项目中使用了Domain driven N-layered application architectureEF code first,我在Domain层中定义了我的Repository契约。一个使其他Repositories不那么冗长的基本约定:

代码语言:javascript
复制
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);
}

和每个Aggregation root的专用Repositories,例如:

代码语言:javascript
复制
public interface IOrderRepository : IRepository<Order, int>
{
    IEnumerable<Order> FindAllOrders();
    IEnumerable<Order> Find(string text);
    //other methods that return Order aggregation root
}

如您所见,所有这些方法都依赖于Domain entities。但在某些情况下,应用程序的UI需要一些非Entity的数据,这些数据可能来自两个或更多的enteritis的数据(View-Model),在这些情况下,我在Application layer中定义了View-Model,因为它们紧密依赖于Application's的需要,而不是Domain

因此,我认为有两种方法可以在UI中将数据显示为View-Models

  1. 将专门化的Repository仅依赖于Entities,并在我想要显示给用户时将Repositories的方法的结果映射到View-Models (在Application Layer Repositories中,一些方法直接将其结果作为View-Models返回,并在D30和D31中使用这些返回值(这些专门化的D32的合同,我称之为D33,不同于其他的D35的合同,放入)。H237<代码>G238

假设我的UI需要一个具有3或4个属性的View-Model (来自3或4个big Entities)。它的数据可以通过简单的投影生成,但是在第一种情况下,因为我的方法不能访问View-Models,所以我必须使用获取所有3个或4个表的所有字段,有时需要使用大型连接,然后将结果映射到View-Models。但是,在第二种情况下,我可以简单地使用投影并直接填充View-Model

因此,我认为从性能的角度来看,情况2比情况1更好。但我读到,从设计的角度来看,Repository应该依赖于Entities而不是View-Models

有没有更好的方法不让Domain层依赖于Application layer,同时又不影响性能呢?或者,对于读取查询,我的Repositories依赖于View-Models是可以接受的吗?(Case2)

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-04-30 04:54:40

也许使用 (在应用程序级别)可能会有所帮助。

您应该使您的存储库仅依赖于实体,并且只将简单的检索方法-即GetOrderById() -保留在您的存储库上(当然还有创建/更新/合并/删除)。设想实体、存储库、域服务、用户界面命令、处理这些命令的应用程序服务(例如,处理web应用程序中的POST请求的某个web控制器等)。表示您的写入模型,即应用程序的写入端

然后构建一个单独的读取模型,它可以像您希望的那样脏-将5个表的连接放在那里,该代码从文件中读取宇宙中的星星数量,将其与以A开头的图书数量相乘(在对亚马逊进行查询之后),并构建一个n维结构,等等--您的想法是:)但是,在读取模型上,不要添加任何涉及修改实体的代码。你可以自由地从这个读取模型返回任何你想要的View-Models,但是从这里触发任何数据改变。

读写的分离应该会降低程序的复杂性,并使一切变得更易于管理。您可能还会看到,它不会违反您在问题中提到的设计规则(希望如此)。

从性能的角度来看,使用读取模型,也就是说,将读取数据的代码与写入/更改数据的代码分开编写是最好的:)这是因为您甚至可以在那里弄乱一些SQL代码,而不会在晚上睡不好觉-如果编写得当,SQL查询将大大提高您的应用程序的速度。

Nota bene:我开了个玩笑,关于你可以编写什么以及如何编写你的读取端代码-读取端代码应该像一样干净的,当然也应该像写入端代码一样简单:)

此外,如果您愿意,您可以摆脱通用存储库接口,因为它只会使您正在建模的领域变得混乱,并迫使每个具体的存储库公开不必要的方法:)请参阅this。例如,Delete()方法很可能永远不会用于OrderRepository -因为订单可能永远不会被删除(当然,这要视情况而定)。当然,您可以将数据库行管理原语保留在单个模块中,并在具体的存储库中重用这些原语,但不要将这些原语暴露给除存储库实现之外的其他任何人-这只是因为其他任何地方都不需要这些原语,如果公开,可能会让喝醉的程序员感到困惑。

最后,也许不以过于严格的方式考虑域层、应用层、数据层或视图模型层也是有益的。请阅读按实际意义/目的(或feature)打包您的软件模块比基于非自然的、难以理解的、难以解释给5岁孩子的标准打包要好一些,也就是说,按打包它们。

票数 22
EN

Stack Overflow用户

发布于 2014-04-30 06:49:07

嗯,对我来说,我会将ViewModel映射到模型对象中,并在我的存储库中使用这些对象进行读/写,正如你可能知道的那样,有几个工具可以做到这一点,在我个人的情况下,我使用automapper,我发现它很容易实现。

尽量保持Web层和Repository层之间的依赖关系,也就是说repos应该只与模型通信,而您的web层应该与视图模型通信。

一种选择是,您可以在服务中使用DTO,并在web层中自动映射这些对象(也可以是一对一的映射)。缺点是,您可能最终会得到大量的样板代码,DTO和视图模型可能会感觉重复。

另一种选择是在模型中返回部分水合对象,并将这些对象公开为DTO,然后将这些对象映射到视图模型。这种解决方案可能有点晦涩难懂,但您可以进行所需的投影,只返回所需的信息。

您可以摆脱视图模型,并在web层中公开dtos,并将其用作视图模型,代码更少,但耦合程度更高。

票数 1
EN

Stack Overflow用户

发布于 2014-05-01 02:53:22

我有点同意佩德罗的观点。使用应用程序服务层可能是有益的。如果您的目标是MVVM类型的实现,我建议您创建一个Model类,负责保存使用服务层检索的数据。如果您的实体、DTO和模型的命名一致,那么使用automapper映射数据是一个非常好的主意(这样您就不必编写大量的手动映射)。

根据我的经验,在视图模型中使用你的实体/poco来显示数据会导致很大的泥球。不同的视图有不同的需求,都会增加向实体添加更多属性的需求。慢慢地使你的查询变得更加复杂和缓慢。

如果您的数据不经常更改,那么您可能需要考虑引入(sql/数据库)视图,将一些繁重的任务转移到数据库(在数据库中进行了高度优化)。EF可以很好地处理数据库视图。然后,检索实体并将数据(从视图)映射到模型或DTO变得相当简单。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23287942

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档