【问题标题】:Abstraction layer between repository and data access code存储库和数据访问代码之间的抽象层
【发布时间】:2012-09-24 16:39:47
【问题描述】:

我尝试将存储库与实际的数据存储实现隔离开来。使用这种抽象创建一些简单的查询几乎没有问题。

例如,我需要按顺序列出订单行数的订单列表。

Repository 方法返回 OrderInfo 对象列表。

class OrderInfo
{
    string Title { get; set; }
    int NumberOfLines { get; set; }
}

数据存储不包含任何直接包含订单行数的字段,因此必须即时计算。

当查询直接写入存储库方法时,可以使用简单的 sql 查询(count + group by)轻松归档。

如果我尝试创建某种抽象层,我迷失了如何“定义查询而不使用任何依赖于存储的东西,包括它应该返回每个订单的订单行数”。

还是我完全走错了方向?

【问题讨论】:

  • 为什么?存储库的目的是将应用程序与数据存储实现隔离开来。你为什么要隔离隔离?对我来说,这听起来像是过度设计。
  • 好吧...我已经读过存储库属于 BLL 但它的实现是在数据层中(无论它在实践中意味着什么)...?如果我有此类 OrderInfo 并将其放入域中(因为它暴露于 UI 并且 UI 不知道数据层)...数据层如何知道有关 OrderInfo 的任何信息?
  • @MystereMan 分层的基本定义是你想要层之间的松散耦合;有时这意味着仅通过抽象进行耦合。
  • @PeterRitchie - 我知道。这就是存储库的重点,它是一个简单的外观。抽象数据层。您通常使用存储库的接口,然后通过构造函数注入将具体实现传递给您的业务对象。

标签: c# ddd-repositories


【解决方案1】:

如果您想允许在 BLL 中使用 IQueryable(我认为应该这样做),那么您可以根据需要定义查询。然后,您的 DAL 应该通过的标准之一是它可以与您的 BLL 一起使用,它应该能够采用 IQueryable,并使用它来读取一些数据。这样你就可以在你的 BLL 中“变得聪明”,并且 DAL 将被抽象出来。

例子:

  • BLL - 使用接口定义它。生成的上下文界面为您提供系统中的所有实体(=表)。这些实体将通过IQueryable<entityType> 提供。实体是使用实体框架 POCO 定义的。
  • DAL - 实体框架上下文,其中上下文实现您在 BLL 中定义的接口。

每一层都在它们自己的程序集中。 DAL 是使用一些依赖注入连接起来的。

记住,这只是一个例子。

更新

阅读 this 关于洋葱架构的文章,这正是您想要做的。

【讨论】:

  • 恕我直言,我认为存储库公开 IQueryable 不是一个好主意。从表面上看,这似乎是一种允许灵活查询的好方法,但这使得单元测试变得非常困难。我发现为返回 IEnumerable 的特定查询实现方法更容易测试和维护。
  • 我已经放弃了IQueryable!我已经尝试了很多次来建立自己的 IQueryProvider 只是为了注意到这是一项非常复杂的任务......
  • 我并不是要编写自己的 IQueryProvider。您将查询传递给应该能够处理它的 dal。
  • 我很久以前就读过那篇洋葱架构文章,但我必须重新思考一下,谢谢!
  • @Maarten - 至少在一个小应用程序中,将 IQueryable 传递给 BLL 不一定是坏事。但是在较大的应用程序中,以及您想要测试每一层的应用程序中,这是一个很大的禁忌。您本质上是将业务逻辑与特定的 DAL 实现联系起来(因为不同的 ORM 以不同的方式实现它们的 Linq)。
猜你喜欢
  • 2012-03-04
  • 1970-01-01
  • 2011-02-19
  • 2010-09-16
  • 2023-03-16
  • 1970-01-01
  • 2013-11-11
  • 2012-12-01
  • 2012-11-22
相关资源
最近更新 更多