DDD中的数据访问层设计

aka*_*key 4 orm domain-driven-design data-access-layer poco

对不起,我的英语很差.

好吧,我现在正在考虑DDD方法,听起来不错但是......有一个小问题.DDD表示,域模型层与数据访问层(以及所有其他层)完全分离.因此,当DAL将保存一些业务对象时,它将只能访问此对象的公共属性.现在的问题是:

我们怎样才能保证(一般来说)对象的一组公共数据是我们以后需要还原对象的全部内容?

我们有以下业务规则:

  1. 必须在创建时为业务对象提供用户和域.
  2. 创建对象后无法更改用户和域.
  3. 业务对象具有Email属性,其类似于"user @ domain".

这是一个描述这些规则的纯POCO:

public class BusinessObject
{
    private string _user;
    private string _domain;

    public BusinessObject(string user, string domain)
    {
        _user = user;
        _domain = domain;
    }

    public string Email
    {
        get { return _user + "@" + _domain; }
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,在某个时刻,DAL会将此对象保存到外部存储(即SQL数据库).显然,DAL会将"Email"属性保存到DB中的关联字段.一切都会正常工作,直到我们要求DAL恢复对象.DAL如何做到这一点?对象必须至少具有"电子邮件"字段的公共设置器.就像是

public string Email
{
    set
    {
        string[] s = value.Split("@");
        _user = s[0];
        _domain = s[1];
    }
}
Run Code Online (Sandbox Code Playgroud)

实际上,该对象将具有"User"和"Domain"字段以及方法GetEmail()的公共getter/setter.但是停下来.我不希望我的POCO拥有这样的功能!它没有业务规则.必须执行此操作才能保存/恢复对象.

我看到另一种选择.可以要求作为DAL一部分的ORM存储恢复对象所需的所有私有字段.但是,如果我们想要将域模型与DAL分开,则这是不可能的.DAL不能依赖业务对象的某些私有成员.

我能看到的唯一解决方法是使用一些系统级工具,可以为我们创建对象转储,并可以随时从此转储中恢复对象.除了对象的公共属性之外,DAL必须将此转储放入存储.因此,当DAL需要从存储中恢复对象时,它将使用转储.当DAL执行不需要实例化对象的操作时(即大多数link2sql查询),可以使用保存到存储的公共属性.

我做错了吗?我需要阅读更多内容吗?关于一些模式,ORM可能吗?

Dmi*_*try 5

我觉得你错了这个部分:

我看到另一种选择.可以要求作为DAL一部分的ORM存储恢复对象所需的所有私有字段. 但是,如果我们想要将域模型与DAL分开,则这是不可能的.DAL不能依赖业务对象的某些私有成员.

域模型不依赖于DAL.相反,DAL依赖于Domain模型.ORM熟悉Domain Objects,包括私有领域.这绝对没有错.实际上,这是在DDD中实现持久无知的最佳方式.这就是Domain类的外观.注意

  • 字段可以是私有的和只读的
  • public构造函数仅由客户端代码使用,而不是由DAL使用.
  • 不需要财产获取者和制定者
  • 业务对象几乎100%不了解持久性问题

DAL/ORM唯一需要的是私有无参数构造器:

public class BusinessObject {
    private readonly string _user;
    private readonly string _domain;

    private BusinessObject(){}

    public BusinessObject(string user, string domain) {
        _user = user;
        _domain = domain;
    }

    public string Email {
        get { return _user + "@" + _domain; }
    }
}
Run Code Online (Sandbox Code Playgroud)

魔术发生在ORM中.Hibernate可以使用此映射文件从数据库恢复此对象:

<class name="BusinessObject" table="BusinessObjects">
    ...
    <property name="_user" column="User" />
    <property name="_domain" column="Domain" />
    ...
</class>
Run Code Online (Sandbox Code Playgroud)

持久性无知域代码的另一个方面是DDD存储库:

定义:存储库是一种封装存储,检索和搜索行为的机制,它模拟对象集合.

存储库接口属于Domain,应尽可能基于泛在语言.另一方面,存储库实现属于DAL(依赖性反转原则).