设计DTO和DO服务层

时间:2013-01-06 15:31:28

标签: domain-driven-design dto service-layer

我正在设计一个新的大型应用程序,该应用程序需要尽可能灵活 我选择主要用DDD设计..
我的问题是关于将DTO对象转移回服务层中的DO对象。

即: 这是我的域对象映射到DB(使用ORM)

public class Cat  
{  
    int ID {get; set;}  
    string Name {get; set;}
    string BloodType {get; set;}
    string Color {get; set;}

    void Run(){...}
    void Purr() {...}
}

只有服务器操作才需要方法和一些属性 这就是我为这种猫类设计另一个数据传输对象的原因:

public class CatDTO 
{  
    int ID {get; set;}  
    string Name {get; set;}
}

在中间,我会设置一个对象映射器,将我的DO转换为DTO(反之亦然)。
当客户想要更新猫的名字时,他会拨打这样的服务

public void UpdateCat(CatDTO cat)  
{
   // What will happen here?
   Cat serverCat = Mapper.GetCat(CatDTO);

   CatDao.SaveOrUpdate(serverCat);
}

当映射器将DTO对象转换回DO时,它必须命中DB以填充Cat对象的缺失属性(血型等等)#9;) 有人说这个动作是荒谬的但是没有填充空属性,服务器端的其余部分无法使用Cat对象,因为它依赖于那些缺少的属性(即使我只是尝试更新数据库中的数据,我的ORM将更新血型字段为空字符串!)
我搜索了这个问题,并且无法在网上找到任何问题(至少有人像我一样对这个问题感到困扰)
我是以错误的方式设计的吗?也许我错过了DDD的东西?
谢谢,帕维尔。

1 个答案:

答案 0 :(得分:4)

此用例的常用工作流程是:按ID检索映射的域对象,应用DTO指定的更新,提交工作单元。您所称的DAO通常称为DDD中的存储库。代码看起来应该更像:

public void UpdateCat(CatDTO catDto)  
{
   Cat cat = this.catRepository.Get(cat.ID);
   cat.Name = catDto.Name;
   this.catRepository.Commit();
}

Commit步骤可以有多种方式。它可以是显式保存,也可以在UpdateCat方法之外提交工作单元。此工作流程也适用于所有相关方案。通常,域行为涉及检索适当的实体,在该实体上调用某些行为,然后将得到的更改提交给数据库。

此外,DTO不应直接映射回现有实体。相反,最好将它们视为表示要应用于现有实体的更改,并且代码应该反映这一点。这部分是因为存储库“拥有”现有实体,而存储库负责重构,而不是DTO映射器。