2013-02-20 91 views
9

我有参与这个问题以下层:查询Repository层中的多个实体时返回什么类型?

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

很多时候,它真的直截了当:库层通过实体框架查询数据库,并返回IList<SomeDomainEntity>对来电者说这是服务层。返回的类型是在域模型中定义的类型。

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

在我看到的例子中,一个匿名类型的课程处理了这个问题,但由于我没有直接在存储库中处理返回数据的逻辑,而需要返回它,所以我需要返回一个物理类型。这里有一些解决方案,我想到了,但不知道我喜欢的:

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

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

谢谢!

+1

我会选择1.根据您的查询创建视图并将视图映射到您的新域模型。 – Romoku 2013-02-20 17:28:56

回答

8

如果这些实体相关和您查询他们都在一个地方,那么你应该尝试找到他们的aggregate root在您的域模型,或者如果它不存在,但你应该引入一个新的,如你在第一个选项中说。这是有道理的,直到它是有道理的。它应该模拟一个域的概念,你可能有一个,因为你创建了这个存储库方法。

如果这些实体不相关(当然,在某些方面可能有关,但不是如上紧),你只想让他们在一个去,那么你应该处理,在服务层,在那里你可以使用多个存储库并撰写结果对象。

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

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

+1

感谢您的帮助,这可以清理很多东西。真正的小细节问题 - 你是否将聚合根实体分离到它们自己的文件夹中,并说'AggregateRootEntities'用于区别? – atconway 2013-02-20 21:14:46

+2

不,这种区别并不那么尖锐,大多数时候他们都是头等公民:)但这并不太重要,所以按照自己感觉舒适的方式组织起来。 – 2013-02-20 21:43:00

+0

因此,让他们驻留在“DomainEntities”或“Entities”文件夹中也可以接受?意思是,我不必如此明确地将它们定义为聚合根实体。 – atconway 2013-02-20 21:58:46

1

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

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

我建议您看看“AutoMapper”。我认为这将是非常有用的,你

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

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

+0

我实际上在我的体系结构的* upper *层中使用DTO和ViewModels,但是我的问题确实集中在* lower *层,包括存储库和域模型。 – atconway 2013-02-20 18:42:43

+0

我认为你的存储库层只需要知道域实体。它是另一层(DDD中的应用程序层)的工作,用于映射和为视图准备此数据 – 2013-02-21 13:20:44

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

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

+0

要将此示例映射到我的示例,我已经有了名为'messages'和'users'的类。然而'UserWithMessages'是我必须创建的,并且像构成2个单独类的某些元素的聚合根一样行事,对吗? – atconway 2013-02-21 17:47:58

+0

这是正确的 – jgauffin 2013-02-21 17:59:29