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

标签 c# wcf entity-framework domain-driven-design

我正在重新设计我当前的项目以使其更易于维护,并尽最大努力遵循良好的设计实践。目前我有一个带有 Silverlight 组件的解决方案,所述 SL 应用程序的 ASP.Net 主机还包含一个 WCF RIA 服务,以及一个共享类库,因此 SL 和 WCF 服务可以共享对象。业务逻辑分散在各处,所有 CRUD 操作都在我的 WCF 服务中手动编码。所以,我正在为所有内容创建一个新结构,并将把这个困惑移植到新格式中。在这样做的过程中,我发现我在重复类(class),但我不知道我是否应该这样做。

我的新结构是这样布局的:

客户:
Reporting.Silverlight = Silverlight 应用程序。这将引用我的 DTO 类。
Reporting.Web = 包含我的 SL 应用程序,是人们访问它的主要入口点。

业务:
Reporting.Services = 我的 WCF 服务在这里。我的 SL 应用程序将调用它来做一些事情,这些服务将返回 DTO 类。
Reporting.Services.Contracts = 保存我的 WCF 服务接口(interface),并包含我的带有 DataContract 装饰器的 DTO 类。
Reporting.Domain = 保存我的域对象和业务逻辑

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

我有 3 个地方有几乎完全相同的类(class),对我来说闻起来很臭。在 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 客户端的一堆属性。除 ID 字段外,我的绝大多数 DTO 属性都以 1:1 的比例映射到我的实体对象的属性。这是与上述 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 个左右的类正在移植并将构成我的领域,我希望一旦我完成重写,这个东西就能扩展到更多的功能。任何关于如何构建这个东西并保持干燥的见解将不胜感激。

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

最佳答案

Having 3 almost identical classes can't possibly be the right way to go about this, can it?

IMO 它们不是“3 个几乎相同的类”,它们的用途不同。它们是同一领域概念的多个方面,每个方面都是针对特定层的需求量身定制的。

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

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

关于c# - 如何减少域/实体/DTO 对象的重复?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18727676/

相关文章:

c# - 收集带有后向和前向链接的 DAG 的所有路径

c# - WCF 服务停止工作 10054 WSAECONNRESET 连接被对等方重置

wcf - Wcf basicHttpBinding 是否支持 PerSession?

c# - EF Core中的0-1自引用关系

sql-server - 将表添加到新 EF 模型时,商店提供商的数据读取器出现错误消息

c# - 使用静态 Regex.IsMatch 与创建 Regex 实例

c# - 表达式树问题 - 如何将实例方法转换为 Func

c# - ShowHelp 功能失败通知

c# - 我们可以在 Web 应用程序中添加对多个 .svc 文件的单一引用吗

asp.net - 无法加载文件或程序集 'MySql.Data,版本 = 6.3.6.0