从集合域驱动设计中删除对象

时间:2014-04-10 11:56:12

标签: entity-framework domain-driven-design

在我们的项目中,我们遵循领域驱动设计与实体框架。最近我遇到了一个问题,我想从集合中删除一个对象。让我们说客户有购买的集合。我想删除一位客户的特定购买。

 public class Customer
{
    public int ID { get; set; }

    public string Name { get; set; }

    public string Address { get; set; }

    public virtual ICollection<Purchase> Purchases { get; set; }
}

public class Purchase
{
    public int ID { get; set; }

    public int CustomerId { get; set; }

    public DateTime PurchaseDate { get; set; }
}

我试图通过

删除购买
customer.Purchases.Remove(purchase);

但上面的代码只删除了不从db中删除购买的关系。我想从db中删除它们。

因此,为了完成这项工作,我已将责任归于Repository并在存储库中使用了上下文对象来删除购买。

repository.DeletePurchase(purchase);

以上是领域驱动设计中的正确方法,还是在实体中移动删除行为的任何可能性?

请帮助我遵循实施DDD的最佳实践。

3 个答案:

答案 0 :(得分:4)

如果您正在关注域驱动设计,an implementation of your collections should follow best practices(例如,应使用AddPurchase / DeletePurchase方法将集合显示为只读,不使用setter。

我认为Purchase未被删除,因为未调用context.SaveChanges()

不幸的是,它也可能是一个已知问题Entity cannot be deleted from child collection but can be from context

编辑: 有两个选项,所有选项都不够好。

  1. context.Set<Purchase>().Remove(purchase);可以被调用。
  2. 复合主键(Id + CustomerId)可用于Purchase实体。

        modelBuilder.Entity<Purchase>()
            .HasRequired(it => it.Customer)
            .WithMany(it => it.Purchases)
            .HasForeignKey(it => it.CustomerId);
    
        modelBuilder.Entity<Purchase>().HasKey(it => new
            {
                Id = it.Id,
                CustomerId = it.CustomerId
            });
    

    默认情况下HasKey()会阻止身份。这就是它应该被指定为属性的原因。

    public class Purchase
    {
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }
    
        public Customer Customer { get; set; }
    
        public int CustomerId { get; set; }
    
        public DateTime PurchaseDate { get; set; }
    }
    
  3. 有一些相关的讨论:

    1. Error when deleting one-to-many children
    2. A relationship is in the Deleted state
    3. Is it possible to remove child from collection and resolve issues on SaveChanges?

答案 1 :(得分:3)

这里要回答的问题是我不知道你正在执行什么行为。 &#34;删除对客户的购买&#34; ......更重要的问题是为什么以及何时允许/适当。即使这样,购买也是一种交易,取消它们的重点是什么(假装它们没有发生,沿途失去了历史)。您的设计也存在问题。如果我每年都购买一些东西怎么办?当我们从现在开始快进一年后,我需要加载多少次购买才能删除单次购买?如何将购买建模为单独的聚合并仅复制客户的ID?我们总能找到客户的所有购买,只使用该客户ID的谓词。这会在你的背景下有意义吗?

人们忘记制定他们试图建模的实际行为的时间和时间,为未来读者添加适当的背景只是一个遥远的梦想。与您的域和模型建立密切关系不是可选的。

答案 2 :(得分:0)

首先,让它发生在域实体上:如果只通过客户的集合访问购买,那么只需将其从那里删除(你现在正在这样做)。

其次,域外的东西需要确保客户被正确地持久存回商店,包括删除购买。有些东西还需要补充你特定的ORM逻辑来实现这一目标。您可以选择的几个选项:

  1. 由于这是特定于EF的问题,请覆盖上下文中的SaveChanges方法,捕获错误,从数据库中删除这些购买(或检查数据库中的哪些购买但不在内存中,然后从DB中删除)

  2. 或者,在负责客户生命周期的应用程序层中,您可以在调用任何服务或实体方法之前跟踪购买ID。然后,当它返回时,您检查客户现在缺少哪些购买ID,调用存储库方法删除它们,并调用存储库SaveChanges()。有点讨厌,因为可能有很多地方你删除了购买。