【问题标题】:asp.net MVC ddd DRY vs loose coupling and persistance/data access layerasp.net MVC ddd DRY 与松散耦合和持久性/数据访问层
【发布时间】:2010-12-14 04:05:54
【问题描述】:

因此,据我了解,它具有良好的松散耦合,我应该能够在应用程序根目录用几行代码替换我的 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 的情况下使用松耦合?

【问题讨论】:

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


    【解决方案1】:

    并不是说我理解正确,但要解决重复的课程,您可以使用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 非常相似,至少在查询语言方面?

    【讨论】:

    • 我并不是要暗示顶部只有几行代码,因为新数据层当然必须编码到每个数据层的应用程序域,但已经编码了 2 行将相同的接口/存储库标准从一个更改为另一个应该是应用程序根目录中的几行代码。我对 automapper 或 EF 没有任何经验,所以我会检查一下,看看它们是否有帮助。我希望不使用 3rd 方库,所以 EF 可能更可取。
    • EF4 也不会在 3 月之前正式发布,对吧?
    • 是的,但它仍然值得一看。例如,请参阅blogs.msdn.com/adonet/archive/2009/07/22/… - 基本上您可以使用 T4 模板从 EF 模型生成任何模型 - 据我了解,这就是您所需要的。如果您不能使用 EF4,请使用 AutoMapper - 我个人不喜欢 EF ;-) 而且 AutoMapper 不仅对 DAL 有帮助。
    • +1 很多优点,尤其是从 AutoMapper 开始作为一种务实的方法。
    • +1 我已经下载并开始使用 Automapper,但我还没有弄清楚是否可以使用它来将视图映射到动态类型。不过,我可以创建一个实现我的接口的运行时类型。马克说我必须制作演示模型,我现在就走那条路,因为我不确定尝试使用这个 beta 代码来实现我希望在 3 月之前个人发布的东西以及工作中的项目的后果。
    【解决方案2】:

    欢迎来到美丽而激动人心的松散耦合代码世界:)

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

    每个域对象的接口甚至对您没有帮助,因为要避免贫血域模型,您需要在域类中实现行为(并且您不能将行为放入接口中)。

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

    我们能希望得到更好的东西吗?是的。我们能得到更好的东西吗?大概。下一个版本的 Entity Framework 将支持 Persistence Ignorance 正是因为这个原因:您应该能够将您的域模型定义为 POCO,如果您提供地图和数据库架构,则 EF 将负责其余的工作。

    在此之前,微软没有提供这种功能的任何东西,但 NHibernate 有(警告:我对 NHibernate 的经验为零,但很多聪明人说这是真的,我相信他们) .这是许多人更喜欢 NHibernate 而不是 EF 的主要原因。

    松耦合需要大量的映射,所以我只能赞同queen3的建议,使用AutoMapper来完成这种繁琐的工作。

    最后,我想指出一个相关问题:映射并不一定意味着违反 DRY。最好的例子是与给定域对象相对应的强类型视图模型。不要被语义相似性所迷惑。它们可能具有或多或少相同的属性和相同的值,但它们的职责却大不相同。随着应用程序的增长,您可能会遇到一些细微的分歧,而且您会很高兴您有这种关注点分离 - 即使它最初看起来像是很多重复的工作。

    无论如何:松耦合在开始时需要做更多的工作,但它可以让您继续开发一个应用程序,而紧耦合的应用程序在很久以前就会在维护地狱中冻结。你是长期的,但不是即时满足。

    【讨论】:

    • +1 很多好主意。也许有一天很快我会给 EF4 或 NHibernate 一个破解。用域对象和自动映射器做我能做的事情
    猜你喜欢
    • 2016-12-04
    • 1970-01-01
    • 2011-02-03
    • 1970-01-01
    • 2010-10-22
    • 2017-11-09
    • 1970-01-01
    • 2011-09-01
    • 1970-01-01
    相关资源
    最近更新 更多