asp.net MVC ddd DRY vs松散耦合和持久性/数据访问层

时间:2009-11-07 14:18:23

标签: asp.net-mvc domain-driven-design dry data-access-layer

因此,我理解它具有良好的松散耦合,我应该能够在应用程序根目录中用几行代码替换掉我的DAL。

我有2个DAL编写,Linq-to-sql和一个JSon文件存储库(用于测试,因为我想试用System.Web.Scripting.JavascriptSerializer)。

linq to sql将创建实体而不是我的商业模式。并通过IRepository向上提供它们,IRepository在应用程序根目录下使用构造函数注入。

我的JSon层没有任何自动生成的类可以反序列化,所以我迷失了一种简单的方法,让它依赖于接口或抽象类并且仍然可以运行。

这个问题基于以下假设/理解:

  • 我相信我需要linq to sql层来实现一个接口,因此编译时的应用程序域可以指示实体类将有一个位置来读/写所有当前模型的字段
  • 任何业务逻辑都要求在模型层中具有几乎相同名称和相同属性的另一组类
    • 然后需要采用DAL对象并将其转换为业务对象并返回的转换方法。 (即使双方都在实现相同的界面,这似乎效率很低)
      • 如果模型类或接口发生变化(接口,业务类,视图,dal实体),此代码是另一个必须进行更改的地方
  • 任何替代DAL的反序列化都要求我创建具有该层中相同属性和字段的“实体”(更多重复)

因此,为了满足所有灵活性/敏捷性目标,我需要为每个应用程序域/业务对象提供一个接口,一个业务逻辑可以存在的具体类,以及实现该接口的DAL对象(这意味着不要使用的层) t自动生成实体必须是手工编码的纯复制。)

如果没有大量重复和丢失DRY,我将如何使用松耦合?

2 个答案:

答案 0 :(得分:5)

欢迎来到松散耦合代码的美丽而令人兴奋的世界:)

您正确理解了问题,但让我首先重申您已经暗示的内容:域模型(即所有域类)必须独立于任何特定的数据访问技术进行定义,因此您不能使用auto-生成LINQ to SQL(L2S)类作为您的Domain类的基础,原因很简单,您无法将这些类与其他技术一起重用(正如您在基于JSON的存储库中发现的那样)。

每个Domain对象的接口甚至无法帮助您,因为要避免使用Anemic Domain Models,您需要在Domain类中实现行为(并且您不能将行为放入接口中)。

这意味着要对Domain对象进行水合和脱水,您必须拥有一些映射代码。它一直是这样的:在过去我们必须从IDataReader实例映射到Domain类,而现在我们需要从Data(L2S)类映射到Domain类。

我们希望有更好的东西吗?是。我们能得到更好的东西吗?大概。实体框架的下一个版本将支持持久性无知,正是出于这个原因:您应该能够将您的域模型定义为POCO,如果您提供地图和数据库模式,EF将负责其余部分。

在此之前,微软没有任何提供这种功能的东西,但NHibernate确实如此(需要注意的是:我对NHibernate没有任何经验,但很多聪明的人都说这是真的,我相信他们) 。这是很多人喜欢NHibernate而不是EF的主要原因。

松耦合需要大量的映射,所以我只能提出使用AutoMapper进行这种繁琐的工作的第二个女王的建议。

作为结束语,我想指出一个相关问题:映射并不一定意味着违反DRY。最好的例子是对应于给定Domain对象的强类型ViewModel。不要被语义相似性所迷惑。它们可能具有或多或少具有相同值的相同属性,但它们的职责差别很大。随着应用程序的增长,您可能会遇到一点点差异在这里和那里潜行,并且您会很高兴您将关注点分开 - 即使它最初看起来像是一些重复的工作。

在任何情况下:松散耦合在一开始就是更多的工作,但它将使您能够继续发展一个紧密耦合的应用程序在维护地狱之前很久就会冻结的应用程序。你是长期的,但不是即时的满足。

答案 1 :(得分:2)

并非我能正确理解问题,但要解决重复的类,您可以使用AutoMapper

请注意,您可以声明性地或使用反射来应用映射,即半自动。例如,请参阅here - 这与数据层无关,但显示了简单属性如何帮助自动化映射。在这种情况下,MVC应用属性,但您可以创建自己的引擎来查找[Entity(“Order”)]属性并应用AutoMapper。

此外,只有“几行”才能实现100%的持久性独立性。 ORM选择在这里起着重要作用。例如,Linq-To-SQL不能使用普通类(POCO),因此重新使用它们并不像NHibernate那样容易。使用Repository,您将在数据层中拥有许多查询;不同的ORM通常具有不同的查询语法或实现(即使Linq并不总是在ORM之间兼容),因此切换数据访问可以完全替换数据层,这不是几行(除非你的应用是“Hello,world!”)

上面的AutoMapper解决方案实际上是一种自制的ORM ......所以你可能需要考虑一个更好的ORM来满足你的需求吗?为什么不使用EF4,特别是考虑到它现在支持POCO,并且与Linq-to-SQL非常相似,至少使用查询语言?