情况:我正在为我的“持久层”使用 LinqToSql(可能被认为是无关紧要的),并试图解决我对某些可疑的业务相关逻辑应该去哪里的一些架构问题。
场景:应用程序的用户创建一个新订单。当他们这样做时,需要将一组产品密钥与该订单相关联。
我的第一次尝试是将所有这些爵士乐放在 OrderService 类中。然后,我尝试使用部分方法将它与我的 DataContext 合并:
partial void InsertOrder(Order instance)
{
var productKeys = this.ProductKeys
.Where(x => x.DeleteDate == null && x.Order == null && !x.Issued)
.Take(instance.NumberOfProductKeys);
if (productKeys.Count() != instance.NumberOfProductKeys)
throw new NotSupportedException("There needs to be more product keys in the database.");
instance.ProductKeys.AddRange(productKeys);
this.ExecuteDynamicInsert(instance);
}
忽略这不能按预期工作的事实(产品密钥实际上从未与订单相关联),我觉得这是从我的业务领域剥离逻辑并将其推送到我的“持久层”。我也想过把它放在一个 OrderService 类中,但觉得它也只是从域实体中拿走了逻辑并导致了一个事务脚本。引入订单工厂只是规避了这个问题:数据和逻辑再次分离。
所以我的问题是:为了避免贫乏的领域模型,并希望除了成为一个美化的数据结构之外还有秩序做一些事情,是否有一种将这种逻辑集成到我的领域模型中的适当方法?
我想出的最佳解决方案是将逻辑放入 Order 类并验证它是否已在验证挂钩中完成:
public partial class Order
{
public void AssociateWithProductKeys(WIIIPDataContext context)
{
var productKeys = context.ProductKeys
.Where(x => x.DeleteDate == null && !x.Issued && x.Order == null && x.ProductType == ProductType)
.Take(NumberOfProductKeys);
if (productKeys.Count() != NumberOfProductKeys)
throw new ValidationException("There needs to be more product keys in the database for product type: " + ProductType.Description);
ProductKeys.AddRange(productKeys);
foreach (ProductKey productKey in ProductKeys)
{
productKey.Issued = true;
}
}
partial void OnValidate(ChangeAction action)
{
if (action == ChangeAction.Insert)
{
if (ProductType.Id == 3 && ProductKeys.Count() != 1)
throw new ValidationException("Attempted to associated more than 1 product key with a CD version.");
if (ProductKeys.Count() != NumberOfProductKeys)
throw new ValidationException("Number of product keys doesn't match expected value");
}
}
}
使用代码如下所示:
// The Unit of Work
using (var context = new MyDataContext())
{
...
order.AssociateWithProductKeys(context);
context.Orders.InsertOnSubmit(order);
context.SubmitChanges();
}
== 2012 年 3 月 29 日更新 ==
在使用 LinqToSQL(和 Web 窗体)时,我采用了命令/查询模式,不再将 LinqToSql DataContext 创建的实体用作到我的数据存储的映射。我所有的规则以及没有进入命令对象的内容,在某种程度上使它们成为应用程序的真正核心。