3

我有一个带有AddUpdateDelete的公共存储库。我们将其命名为CustomerRepository

我有一个名为Customer的实体(POCO) ,它是一个聚合根,带有Addresses

public class Customer
{
     public Address Addresses { get; set; }
}

我处于分离实体框架 5 场景中。

现在,假设在获得客户后,我选择删除客户地址。我通过Update方法将Customer聚合根提交到存储库。

如何保存对地址所做的修改?

  1. 如果地址 id 为 0,我可以假设地址是新的。
  2. 对于地址的其余部分,我可以选择附加所有地址,无论如何都将其标记为已更新。
  3. 对于已删除的地址,我看不到任何解决方法...

我们可以说这个解决方案是不完整和低效的。

那么应该如何更新聚合根子节点呢?

我是否必须使用AddAddressUpdateAddressDeleteAddress等方法完成CustomerRepository

似乎它会打破这种模式......

我是否在每个 POCO 上设置了持久性状态:

public enum PersistanceState
{
     Unchanged,
     New,
     Updated,
     Deleted
}

然后在我的CustomerRepository中只有一种方法Save

在这种情况下,我似乎正在重新发明实体“非 POCO”对象,并将数据访问相关属性添加到业务对象......

4

2 回答 2

2

First, you should keep your repository with Add, Update, and Delete methods, although I personally prefer Add, indexer set, and Remove so that the repository looks like an in memory collection to the application code.

Secondly, the repository should be responsible for tracking persistence states. I don't even clutter up my domain objects with

object ID { get; }

like some people do. Instead, my repositories look like this:

public class ConcreteRepository : List<AggregateRootDataModel>, IAggregateRootRepository

The AggregateRootDataModel class is what I use to track the IDs of my in-memory objects as well as track any persistence information. In your case, I would put a property of

List<AddressDataModel> Addresses { get; }

on my CustomerDataModel class which would also hold the Customer domain object as well as the database ID for the customer. Then, when a customer is updated, I would have code like:

public class ConcreteRepository : List<AggregateRootDataModel>, IAggregateRootRepository
{
    public Customer this[int index]
    {
        set
        {
            //Lookup the data model
            AggregateRootDataModel model = (from AggregateRootDataModel dm in this
                                           where dm.Customer == value
                                           select dm).SingleOrDefault();
            //Inside the setter for this property, run your comparison 
            //and mark addresses as needing to be added, updated, or deleted.
            model.Customer = value;
            SaveModel(model); //Run your EF code to save the model back to the database.
        }
    }
}

The main caveat with this approach is that your Domain Model must be a reference type and you shouldn't be overriding GetHashCode(). The main reason for this is that when you perform the lookup for the matching data model, the hash code can't be dependent upon the values of any changeable properties because it needs to remain the same even if the application code has modified the values of properties on the instance of the domain model. Using this approach, the application code becomes:

IAggregateRootRepository rep = new ConcreteRepository([arguments that load the repository from the db]);
Customer customer = rep[0]; //or however you choose to select your Customer.
customer.Addresses = newAddresses;  //change the addresses
rep[0] = customer;
于 2012-12-14T23:09:58.147 回答
1

最简单的方法是使用自我跟踪实体自我跟踪实体的目的是什么?(我不喜欢它,因为跟踪是不同的责任)。

艰难的方式,你拿原来的收藏,然后比较:-/

保存 EF4 POCO 对象的更改时更新关系

其他方式可能是事件跟踪?

于 2012-12-13T15:54:42.127 回答