Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 到目前为止;别把它扔掉_.net_Serialization_Orm_Mapping_Dto - Fatal编程技术网

.net 到目前为止;别把它扔掉

.net 到目前为止;别把它扔掉,.net,serialization,orm,mapping,dto,.net,Serialization,Orm,Mapping,Dto,考虑一下web服务是什么。它不仅仅是对ORM的抽象;这是一份合同。它是一个面向内部和外部客户的公共API 公共API应该没有任何理由进行更改。除了添加新的类型和方法外,对API的任何更改几乎都是一个突破性的更改。但是你的领域模型不会那么严格。当您添加新功能或发现原始设计中的缺陷时,您需要不时对其进行更改。您希望能够确保对内部模型的更改不会导致通过服务契约的级联更改 实际上,出于类似的原因,为每条消息创建特定的请求和响应类是一种常见做法(我不会用“最佳做法”来侮辱读者);扩展现有服务和方法的功能而

考虑一下web服务是什么。它不仅仅是对ORM的抽象;这是一份合同。它是一个面向内部和外部客户的公共API

公共API应该没有任何理由进行更改。除了添加新的类型和方法外,对API的任何更改几乎都是一个突破性的更改。但是你的领域模型不会那么严格。当您添加新功能或发现原始设计中的缺陷时,您需要不时对其进行更改。您希望能够确保对内部模型的更改不会导致通过服务契约的级联更改

实际上,出于类似的原因,为每条消息创建特定的
请求
响应
类是一种常见做法(我不会用“最佳做法”来侮辱读者);扩展现有服务和方法的功能而不破坏它们的更改,这将变得简单得多

客户可能不希望您在服务内部使用完全相同的模型。如果您是您唯一的客户机,那么这可能看起来是透明的,但是如果您有外部客户机,并且已经看到他们对您的系统的解释通常有多远,那么您将理解不允许您的完美模型泄露服务API限制的价值


有时,甚至不可能通过API将模型发送回。出现这种情况的原因有很多:

  • 对象图中的循环。在OOP中非常好;连载的灾难性。最终,您必须做出痛苦的永久性选择,确定图形必须序列化的“方向”。另一方面,如果您使用DTO,则可以按照您想要的任何方向进行序列化,只要适合手头的任务即可

  • 试图在SOAP/REST上使用某些类型的继承机制充其量只能是一个难题。旧式XML序列化程序至少支持
    xs:choice
    DataContract
    没有,我也不会质疑其基本原理,但我只想说,您的富域模型中可能存在一些多态性,而且几乎不可能通过web服务来传递这些多态性

  • 延迟/延迟加载,如果使用ORM,您可能会使用它。确保它被正确序列化已经够麻烦的了——例如,使用Linq to SQL实体,WCF甚至不会触发延迟加载程序,它只会将
    null
    放入该字段,除非您手动加载它——但对于返回的数据,问题会变得更糟。像在构造函数中初始化的
    List
    auto属性这样简单的东西(在域模型中非常常见)在WCF中根本不起作用,因为它不会调用构造函数。相反,您必须添加一个
    [OnDeserialization]
    初始值设定项方法,并且您真的不想用这种垃圾把域模型弄得乱七八糟

  • 我还注意到了你使用NHibernate的附加说明。考虑到在Web服务上不能像“代码> ILIST < /代码>这样的接口被序列化!如果像我们大多数人一样,将POCO类与NHibernate一起使用,那么这根本不起作用


当您的内部域模型与客户机的需求不匹配时,也可能会出现许多情况,并且更改域模型以适应这些需求是没有意义的。作为一个例子,让我们以发票这样简单的东西为例。它需要表明:

  • 有关帐户的信息(帐号、名称等)
  • 发票特定数据(发票编号、日期、到期日等)
  • 应收级别信息(以前余额、延迟费用、新余额)
  • 发票上所有内容的产品或服务信息
  • 等等
这可能很适合域模型。但是,如果客户希望运行一个显示1200张发票的报告,该怎么办?什么对账报告

这对于序列化来说太糟糕了。现在,您正在发送1200张发票,其中的相同的数据被一次又一次地序列化-相同的帐户、相同的产品、相同的应收帐款。在内部,您的应用程序正在跟踪所有链接;它知道发票#35和发票#45是针对同一客户的,因此共享
客户
参考;所有这些信息在序列化时都会丢失,最终会发送大量冗余数据

您真正想要的是发送一份自定义报告,其中包括:

  • 报告中包括的所有账目及其应收账款
  • 报告中包含的所有产品
  • 所有发票,仅带有产品和帐户ID
如果希望避免大量冗余,则需要在将传出数据发送到客户端之前对其执行额外的“规范化”。这极有利于DTO方法;在域模型中使用这种结构是没有意义的,因为域模型已经以自己的方式处理了冗余


我希望这些都是足够的例子和理由,能够说服您保持域服务契约中的映射完好无损。到目前为止,您做了完全正确的事情,您的设计非常棒,如果您放弃了所有的努力,转而去做一些可能会导致以后严重头痛的事情,那将是一件非常遗憾的事情。

您绝对应该将域实体与DTO分开,因为它们是不同的关注点。DTO通常是heriachal的自描述模型,另一方面,作为您的域实体,它封装了您的业务逻辑,并附带了许多行为

话虽如此,我不确定额外的映射在哪里? 您使用ORM(又名域实体)检索数据,并将这些对象映射到DTO,因此那里只有一个映射?顺便说一句,如果你不是艾尔
var employee = Map<Employee>.from_dto<EmployeeDto>();