如何减少域/实体/ DTO对象的重复?

Bil*_*one 20 c# wcf domain-driven-design entity-framework

我正在重新设计我当前的项目以使其更易于维护,并尽力遵循良好的设计实践.目前我有一个Silverlight组件的解决方案,用于所述SL应用程序的ASP.Net主机,该应用程序还包含WCF RIA服务和共享类库,因此SL和WCF服务都可以共享对象.业务逻辑遍布各处,所有CRUD操作都在我的WCF服务中手动编码.所以,我正在为一切创建一个新结构,并将这个混乱移植到新格式中.在这样做的过程中,当我不知道自己是否应该这样时,我发现我正在复制课程.

我的新结构如下:

客户端:
Reporting.Silverlight = Silverlight应用程序.这将参考我的DTO课程.
Reporting.Web =持有我的SL应用程序,是人们进入它的主要入口点.

业务:
Reporting.Services =我的WCF服务就在这里.我的SL应用程序将调用此方法来执行操作,这些服务将返回DTO类.
Reporting.Services.Contracts =保存我的WCF服务接口,并包含带有DataContract装饰器的DTO类.
Reporting.Domain =保存我的域对象和业务逻辑

数据:
Reporting.Data.Contract =保存我的存储库和工作单元的接口
Reporting.Data=存储库/ UoW的具体实现.此处定义了Entity Framework 5上下文.
Reporting.Data.Models =保存我的所有Entity对象,以便EF5可以用SQL做它的事情.

我有3个地方,我几乎完全相同的课程,对我来说它闻起来.在Reporting.Services.Contracts内部,我有一个DTO,可以交给SL客户端.这是一个例子:

[DataContract(Name = "ComputerDTO")]
public class ComputerDTO
{
    [DataMember(Name = "Hostname")]
    public string Hostname { get; set; }

    [DataMember(Name = "ServiceTag")]
    public string ServiceTag { get; set; }

  // ... lots more
}
Run Code Online (Sandbox Code Playgroud)

我认为上面的DTO很好,因为它只是传递给SL客户端的一堆属性.我的DTO属性的绝大多数都映射到我的实体对象1:1的特性,除了ID字段.这是我的Entity对象,与上面的DTO对应:

[Table("Inventory_Base")]
public class ComputerEntity
{
    // primary key
    [Key]
    public int AssetID { get; set; }

    // foreign keys
    public int? ClientID { get; set; }

    // these props are fine without custom mapping
    public string Hostname { get; set; }
    public string ServiceTag { get; set; }
    // ... plus a bunch more in addition to my navigation properties
}
Run Code Online (Sandbox Code Playgroud)

我正在使用EF5的代码优先方法.我仍然处于重写的最初阶段,到目前为止,我的印象是业务逻辑不应该在我的EF实体中.DTO也不应该有业务逻辑.这意味着它进入了我的域模型,对吗?好吧,这给了我在Reporting.Domain中的第3个几乎相同的类

public class Computer
{
   public string Hostname { get; set; }
   public string ServiceTag { get; set; }
   // ... lots more, pretty much mirrors the DTO

   public string Method1(string param1)
   {
       // lots of methods and logic go in here
   }
}
Run Code Online (Sandbox Code Playgroud)

拥有3个几乎完全相同的课程可能不是正确的方法,可以吗?我应该将所有业务逻辑放在EF实体中,然后将结果投影到通过线路传递的DTO中吗?如果将所有域/业务逻辑塞入EF实体类中是个好主意,那么在结构上我应该将该程序集移动到我的业务层和数据层之外,即使这些对象是保存到我的数据库的对象?理想情况下,我试图在我的数据项目中和业务项目之外保留对Entity Framework的任何引用.我有大约200个左右的类,我正在移植并将构成我的域,并且我希望一旦我完成重写,这个东西可以扩展到更多的功能.

如果它有助于定义我想要做的更好,请告诉我是否应该包含我所遵循的我的存储库/单元工作方法.

gui*_*e31 24

拥有3个几乎完全相同的课程可能不是正确的方法,可以吗?

IMO他们不是"3个几乎相同的班级",他们没有达到同样的目的.它们是相同领域概念的多个方面,每个方面都针对特定层的需求而定制.

这是模块化和明确的关注点分离的代价.您拥有的端口越多(如Hexagonal Architecture的端口和适配器),您需要的方面越多,您需要做的映射就越多.

一篇很好的文章:http://blog.ploeh.dk/2012/02/09/IsLayeringWorththeMapping/

  • 我只使用过 AutoMapper (https://github.com/AutoMapper/AutoMapper),它对我很有用 (2认同)