c# - 将 View 模型与存储库模式结合使用

标签 c# entity-framework ef-code-first repository viewmodel

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

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

和专业Repositories每个Aggregation root ,例如:

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 的数据,该数据可能由两个或多个肠炎数据(View-Model s)组成,在这些情况下,我定义了View-ModelApplication layer ,因为它们密切依赖于 Application's需要而不是 Domain .

所以,我认为我有 2 种方法可以将数据显示为 View-ModelsUI :

  1. 离开专业Repository取决于 Entities只,并映射 Repositories 的结果View-Models 的方法当我想向用户展示时(通常在 Application Layer 中)。
  2. 为我的专业 Repositories 添加一些方法返回结果为 View-Models直接,并在 Application Layer 中使用这些返回值然后 UI (这些专门的 Repositories 的合约,我称之为 Readonly Repository Contract s,放入 Application Layer 不同于其他 Repositories 放入 Domain 的合约)。 enter image description here

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

所以,我认为从性能的角度来看,案例 2 比案例 1 好。但我读到 Repository应该取决于 Entities而不是 View-Models从设计的角度来看。

有没有更好的方法不会导致 Domain层取决于 Application layer ,也不影响性能?或者对于阅读查询,我的 Repositories 是否可以接受取决于 View-Models ?(案例2)

最佳答案

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

您应该让您的存储库仅依赖于实体,并且只保留琐碎的检索方法 - 即 GetOrderById() - 在您的存储库中(连同创建/当然是更新/合并/删除)。想象一下,实体、存储库、领域服务、用户界面命令、处理这些命令的应用程序服务(例如,在 Web 应用程序中处理 POST 请求的某个 Web Controller 等)代表您的 write模型,您的应用程序的写入端

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

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

从性能的角度来看,使用读取模型,即将读取数据的代码与写入/更改<的代码分开编写/strong> 数据是你能得到的最好的 :) 这是因为你甚至可以在晚上不睡不好的情况下在那里修改一些 SQL 代码——而且 SQL 查询,如果写得好,会给你的应用程序带来相当大的速度提升。

Nota bene:我开玩笑说您可以为读取端编写什么以及如何编写代码 - 当然,读取端代码应该像写入端代码一样干净和简单: )

此外,如果您愿意,您可以摆脱通用存储库接口(interface),因为它只会使您正在建模的域变得困惑,并迫使每个具体的存储库公开不必要的方法:) 请参见 this .例如,Delete() 方法很可能永远不会用于 OrderRepository - 因为,也许永远不应该删除 Orders(当然,一如既往,这取决于)。当然,您可以将 database-row-managing 原语保留在单个模块中,并在您的具体存储库中重用这些原语,但不要将这些原语公开给存储库的实现以外的任何其他人 - 仅仅是因为它们在其他任何地方都不需要,如果公开暴露可能会使醉酒的程序员感到困惑。

最后,或许不考虑领域层应用层数据层 View 模型也会有好处以过于严格的方式分层。请阅读 this. 按现实世界的意义/目的(或功能)打包软件模块比基于不自然硬-理解hard to explain-to-a-5-old-kid 标准,即按层包装它们。

关于c# - 将 View 模型与存储库模式结合使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23287942/

相关文章:

c# - C# 的 C 库从操作系统队列中删除消息

c# - Entity Framework 数据库首先自动验证属性的最大长度

c# - 访问/使用 View Entity Framework 6 Code First 方法

linq - C# EF5 Code First 中多对多关系的 Lambda 表达式

c# - 将字节数组转换为 int

c# - 计算的进度百分比未更新

entity-framework - Entity Framework 4 - 将现有模型添加到关联中

c# - 使用 Entity Framework 执行 SQlite 命令

c# - 对象与集合的 Entity Framework 更新方法

c# - 将数据加载到动态填充的部分 View 中的选择下拉菜单