在Repository层中查询多个实体时要返回什么类型?

时间:2013-02-20 17:22:34

标签: c# entity-framework repository-pattern

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

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

很多时候它非常直接:存储库层通过Entity Framework查询数据库并将IList<SomeDomainEntity>返回给服务层的调用者。返回的类型是域模型中定义的类型。

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

一个匿名类型的课程在我看到的示例中处理这个问题,但由于我不是直接在Repository中处理返回数据中的那个逻辑而需要返回它,我需要一个物理类型来返回。以下是我想到的一些解决方案,但不确定我是否喜欢:

  1. 在域模型中创建一个新的域实体,它实际上是我查询的所有数据的组合,因此可以返回这个新的单一类型。创建abritrary类型以满足查询需求似乎是错误的。
  2. 使服务层分别调用A,B,C实体上的各个存储库,然后处理每个返回对象的数据。这似乎是一项额外的工作。
  3. 创建要返回的ViewModel。这对我来说似乎也不合适。我在服务层和UI层之间大量使用ViewModel类,但从来没有看到它们用于从存储库返回。
  4. 我不可能是唯一一个查询多个实体以获取需要添加到类型并返回给调用者的数据集合的人。为解决我的问题,通常的做法或标准方法是什么?

    谢谢!

3 个答案:

答案 0 :(得分:8)

如果这些实体相关,并且您在一个地方查询所有实体,那么您应该尝试在您的域模型中找到aggregate root个实体,或者它们是否仍然存在你应该引入一个新的,正如你在第一个选项中所说的那样。直到它有意义才没有错。它应该为域概念建模,您可能有一个,因为您创建了该存储库方法。

如果这些实体不相关(好吧,可能在某种程度上相关,但不是如上所述)并且您只想一次性获取它们,那么您应该在服务中处理它们您可以使用多个存储库并组成结果对象的图层。

您可能听说过navigation propertieseager loading的概念,但我在这里写的是因为它可能是您问题的另一个答案(我没有看到您的域模型)

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

答案 1 :(得分: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));
    }
}

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

答案 2 :(得分:1)

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

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

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

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

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