2010-11-17 88 views
0

以下是故事:一个网站(感兴趣的物理位置)具有零个或多个联系人。这些联系人是与有权处理本网站事务的公司有关的人员。FluentNH将“深”关系模型映射到“展平”域对象

的模式是这样的:

Person -< CompanyContact -<CompanySiteContact>- Site 
    || 
    | -< PersonPhone 
    | 
    -< PersonAddress 

我的切入点是网站。我需要联系人列表。除非你到达人员,否则很少有感兴趣的现场数据。所以,我想将Person,CompanyContact和CompanySiteContact合并为一个域类。

的选项,我想出了:

  • 创建一个域类和使用在FluentNH地图加入到拼合图层,因为它检索数据 。它从来没有听起来简单,我遇到了多级联接的问题(如果A联接B联接C,则不能在与B的联接中指定与C的联接)。然而,我认为,如果可以指定连接,那只是一次性的事情,所以这将最终成为最可维护的解决方案。

  • 在一组“DTO”中复制深层模型,该模型将1:1映射到表并可以传递给“平坦”域模型的构造函数。它的工作原理,但它感觉就像作弊(没有任何问题不能用另一层抽象层解决,除了有太多的抽象层),我的直觉告诉我,这最终会导致更多的问题,而不是解决问题。

  • 使用架构复制域模型1:1并使用CompanySiteContact上的传递属性访问属性在人员记录深处的属性。再一次,现在起作用,但它并不能真正解决问题,每一个变得有趣的新属性都需要对映射,实际域类和顶级域类进行更改。不是很固体。

所以,Q是,我将如何构建映射?就像我说过的,我无法在连接中指定连接。我认为我必须这样做的方式是映射每个表的PK,并在顶层的下一个连接中使用它,但我不确定如何设置它(没有使用FluentNH来设置任何接近这个复杂的东西)。

回答

0

感谢詹姆斯的回答; +1,但我认为AutoMapper在这个时候不是必须的,而且我有点不自在地加入了能够“自动”完成这项工作的东西。我想到了更多的选择:

  • 在DB中设置视图。这将工作,因为由于业务规则,联系人信息是只读的;我正在开发的应用程序不能直接更新联系人,因为不同的部门维护此rolodex。

  • 按照James的建议映射我的域名1:1,但是随后使用Linq查询将模型拼合成DTO。这个查询可以封装在Repository的帮助器中,允许开发人员直接使用Repository上的相同方法来查询DTO和其他类。它比具有相同结果的视图更复杂,但它不需要模式更改。

我可能会去第一个选项,如果有必要的话可以使用第二个选项。

+0

或者您可以使用AutoMapper轻松一点?你的替代方案听起来像是你在游戏后期为自己设定了一个大泥球,尤其是你的第二选择。说真的,一切都很神奇,直到你明白它是如何工作的。花一个小时玩AutoMapper,它会为你节省很多痛苦。 – 2010-12-06 17:15:34

+0

好吧,我花了一点时间来看看AutoMapper,并且发现它比我在最初的样子中看到的有更灵活(可定义)的配置选项。使用自定义映射,这是一个可行的,可维护的工具。我称之为“黑魔法”,因为在“Mapper.CreateMap ()”的最简单情况下,依靠默认的命名约定,在代码中没有任何东西可以指向映射得以实现。这将给一名开发人员带来史诗般的偏头痛,他们重新命名了一个房产,并且没有明显的理由打破了整个应用程序。 – KeithS 2010-12-06 18:23:41

+0

我认为这个问题不是AutoMapper的“魔力”,而是开发者的教育。这同样适用于Fluent NHibernate中的约定,StructureMap或Castle中的自动装配,MVC中的路由;如果你只是参加并开始改变事情,那么除非你已经接受了有关这些约定的教育,否则这些东西将会被打破。明确定义一切是避免教育开发人员的一种痛苦方式。 – 2010-12-08 09:26:37

2

我建议创建您的域模型以紧密匹配您的数据库。从那里我创建DTOs并使用AutoMapper来压扁。简单。

+0

+1,但我不认为我们会使用AutoMapper。显然,可配置性有点不理想,因此当代码稍后维护时,它可能看起来像“黑魔法”。 – KeithS 2010-12-06 15:52:33