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

我正在重新设计我当前的项目以使其更易于维护,并尽力遵循良好的设计实践。 目前我有一个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 } 

我认为上面的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 } 

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

 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 } } 

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

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

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

IMO他们不是“3个几乎相同的类”,他们不是为了同一个目的。 它们是相同领域概念的多个方面,每个方面都针对特定层的需求而定制。

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

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