【发布时间】:2011-05-05 22:42:41
【问题描述】:
假设我有一个包含 Customer 对象和 SalesOrder 对象的通用模式。我有相应的 SalesOrderContract 和 CustomerContract 对象,它们是相似的、更扁平的对象,用于通过 Web 服务进行序列化
public class Customer
{
public int CustomerId { get; set; }
public string Name { get; set; }
public Address ShippingAddress { get; set; }
//more fields...
}
public class Order
{
public int OrderId { get; set; }
public Customer Customer { get; set;
// etc
}
我的销售订单合同是这样的
public class OrderContract
{
public int OrderId { get; set; }
public int CustomerId { get; set; }
}
public class OrderTranslator
{
public static Order ToOrder(OrderContract contract)
{
return new Order { OrderId = contract.OrderId };
// just translate customer id or populate entire Customer object
}
}
我在服务层和业务对象层之间有一个层,在两者之间进行转换。我的问题是……我是否在另一端填充 Order.Customer 对象,因为 Order 表只需要客户 ID。我没有在 OrderContract 中携带整个客户对象,因为它没有必要而且太重。但是,作为保存它的一部分,我必须验证它确实是一个有效的客户。我可以做一些事情
- 当我在合同和实体之间进行转换时,完全基于 CustomerId 填充 Order.Customer 对象。这需要在实体和合同之间转换的帮助器类中调用 CustomerRepository。我觉得不对。翻译器应该只是数据映射。
- 为每组执行所需验证的操作创建一个域服务,而无需填充 Order.Customer。该服务将根据 Order.CustomerId 拉取 Customer 对象并检查它是否有效。对此不确定,因为销售订单应该能够自我验证,但它也没有明确处理订单,因为它也处理客户,所以可能是域服务?
- 创建一个单独的属性 Order.CustomerId 并在此基础上延迟加载客户对象。
- 从工厂类中填充 Order.Customer。现在我的工厂类只是为了从数据库加载。我并没有真正从数据合同中加载,但也许这有意义?
所以问题是两部分...如果您的实体中有关联属性,需要在保存之前判断某些内容是否完全有效,您是否只是填充它们?如果你这样做了,你实际上在哪里这样做,因为合同/实体翻译感觉不对?
底线是我需要能够做类似的事情
if (order.Customer == null || !order.Customer.IsActive)
{
//do something
}
问题是这样做有什么意义?实际上,我的 Order 对象有很多验证所需的子实体,我不希望事情变得臃肿。这就是为什么我正在考虑制作域服务来封装验证,因为在我的特定情况下它是一个如此巨大的操作(数百个奇怪的规则)。但我也不想删除所有使我的对象只是属性的逻辑。找到平衡很难。
希望这是有道理的。如果需要更多背景知识,请告诉我。
【问题讨论】:
-
有人吗?如果你有观点,请分享一下?
-
我一直在做更多的研究,我发现在创建新实体时,填充实体对象没有多大意义,因为它实际上并不在数据存储中。好的,我明白这一点,但是如果您需要进行复杂的验证(不仅仅是属性级别的东西),并且您没有完全填充的实体,那么您到底是如何做到的。
标签: wcf domain-driven-design datacontract