【发布时间】:2013-09-14 16:19:15
【问题描述】:
我正在重新设计我当前的项目以使其更易于维护,并尽我所能遵循良好的设计实践。目前,我有一个带有 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 服务接口,并包含我的 DTO 类DataContract 装饰器。
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 字段除外。这是与上述 DTO 对应的我的 Entity 对象:
[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 实体类中是个好主意,那么在结构上我是否应该将该程序集移动到我的业务层和数据层之外,即使这些对象是保存到我的数据库中的对象?理想情况下,我试图保留对实体框架的任何引用,这些引用包含在我的数据项目中和我的业务项目之外。我有大约 200 个要移植的类,它们将构成我的域,我希望一旦完成重写,这个东西可以扩展到更多的功能。任何有关如何构建此东西并使其保持干燥的见解将不胜感激。
如果它有助于定义我想要做的更好的事情,请告诉我是否应该包含我正在遵循的存储库/工作单元方法。
【问题讨论】:
-
嗨格特 - 我喜欢你在那个链接问题中的回答,它对我来说很清楚。我的理解是,如果实体对象相同且实用,则可以将它们用作域对象。但是,我确实希望我以后添加的域类与我的实体对象不同。在这种情况下,我是否仍需要在 DTO/Domain/Entity-for-my-ORM 之间将我的课程分成三份?
-
DTO/Domain/Entity 解决方案旨在为单独的关注点建立单独的专有模型。只有当持久性基础设施阻碍您构建细化域模型时,实体才有意义。如果您的域不是那么复杂,您可以使用实体作为域模型。 DTO 也是如此。
-
@BillSambrone 对于部分域,可能。在实体模型结构妨碍简洁业务逻辑编程的地方,必须创建专用的领域类。这些类在实体模型中没有直接对应物,因此不再是三重复制(或重复)。 映射在这里是一个更合适的术语。 DTO 也是如此。当 UI 层需要在实体模型中不匹配的扁平/聚合数据结构时,我经常使用 DTO 而不是实体。如果您想将表示层与数据/业务逻辑分离,也必须使用 DTO。
标签: c# wcf entity-framework domain-driven-design