10

我在这个问题中涉及以下层:

  • 服务层(使用 IoC 调用 Repository)
  • 域模型(POCO / 域实体,定义的存储库接口)
  • 存储库层(EF .edmx 和实施的存储库)

很多时候它真的很简单:存储层通过实体框架查询数据库并返回IList<SomeDomainEntity>给服务层的调用者。返回的类型是领域模型中定义的类型。

我遇到的问题是当我需要查询 POCO A、B 和 C 并从所有要​​返回的数据中获取数据时。由于我不处理存储库中的任何逻辑,因此我需要将此数据返回到服务层进行处理(直接或更有可能通过调用域模型上的某些逻辑)。但是,我不再有从存储库查询结果返回给调用者的单一类型。

在我看到的示例中,一个匿名类型当然会处理这个问题,但由于我没有直接在存储库中处理来自返回数据的逻辑并且它需要返回,所以我需要一个物理类型来返回。以下是我想到的一些解决方案,但不确定我是否喜欢:

  1. 在域模型中创建一个新的域实体,它本质上是我查询的所有数据的组合,因此可以返回这个新的单一类型。创建满足查询需求的任意类型似乎是错误的。
  2. 使服务层分别调用 A、B、C 实体上的各个存储库,然后处理来自每个返回对象的数据。这似乎是很多额外的工作。
  3. 创建要返回的 ViewModel。这对我来说似乎也不合适。我在服务层和 UI 层之间大量使用 ViewModel 类,但从未见过它们被用于从存储库返回。

我不能是唯一一个跨多个实体查询以获取需要添加到类型并返回给调用者的数据集合的人。解决我的问题的常见做法或标准方法是什么?

谢谢!

4

3 回答 3

8

如果这些实体是相关的并且您在一个地方查询所有这些实体,那么您应该尝试在您的域模型中找到它们的聚合根,或者如果它还不存在,您应该引入一个新的,正如您在第一个中所说选项。在有意义之前,这没有错。它应该对域概念进行建模,并且您可能拥有一个,因为您创建了该存储库方法。

如果这些实体不相关(嗯,可能以某种方式相关,但不像上面那样紧密)并且您只想一次性获取它们,那么您应该在服务层中处理它,您可以使用多个存储库并组成一个结果对象。

您可能听说过导航属性急切加载的概念,但我在这里写它是因为它可能是您问题的另一个答案(我没有看到您的域模型)

我不会接受您的第三个建议(在存储库中创建视图模型),因为它打破了分隔。

于 2013-02-20T17:55:54.133 回答
3

不同的实体可以相互关联,但其中一个实体不是聚合根。服务用于此类查询。我通常会这样做:

public class MyService
{
    IEnumerable<UserWithMessages> Find()
    {
        var messages = _messageRepository.FindAll();
        var userIds = _messages.Select(x => x.UserId).Distinct().ToArry();
        var users = _userRepository.Find(userIds);
        return users.Select(x => new UserWithMessages(x, messages.Where(x => x.UserId == x.Id));
    }
}

它只是两个可以利用数据库中的索引的数据库查询。所以应该很快。

于 2013-02-21T07:07:43.177 回答
1

我建议您为此目的使用 DTO(数据传输对象)。将服务层与视图分离是一种常见的做法,而 DTO 允许您仅共享视图所需的重要信息。

根据系统的大小,有多种方法可以实现系统的这一部分。在小型系统中,您可以使用扩展方法将 POCO 实体映射到数据传输对象中

我建议你看看“AutoMapper”。我认为这对您非常有用

http://www.codeproject.com/Articles/61629/AutoMapper

http://lostechies.com/jimmybogard/2009/01/23/automapper-the-object-object-mapper/

于 2013-02-20T17:58:17.603 回答