Domanda

How can we tell Entity Framework about Aggregates?

  1. when saving an aggregate, save entities within the aggregate
  2. when deleting an aggregate, delete entities within the aggregate
  3. raise a concurrency error when two different users attempt to modify two different entities within the same aggreate
  4. when loading an aggregate, provide a consistent point-in-time view of the aggregate even if there is some time delay before we access all entities within the aggregate

(Entity Framework 4.3.1 Code First)

È stato utile?

Soluzione

EF provides features which allows you defining your aggregates and using them:

  1. This is the most painful part. EF works with entity graphs. If you have an entity like Invoice and this entity has collection of related InvoiceLine entities you can approach it like aggregate. If you are in attached scenario everything works as expected but in detached scenario (either aggregate is not loaded by EF or it is loaded by different context instance) you must attach the aggregate to context instance and tell it exactly what did you changed = set state for every entity and independent association in object graph.
  2. This is handled by cascade delete - if you have related entities loaded, EF will delete them but if you don't you must have cascade delete configured on the relation in the database.
  3. This is handled by concurrency tokens in the database - most commonly either timestamp or rowversion columns.
  4. You must either use eager loading and load all data together at the beginning (= consistent point of view) or you will use lazy loading and in such case you will not have consistent point of view because lazy loading will load current state of relations but it will not update other parts of aggregate you have already loaded (and I consider this as performance killer if you try to implement such refreshing with EF).

Altri suggerimenti

I wrote GraphDiff specifically for this purpose. It allows you to define an 'aggregate boundary' on update by providing a fluent mapping. I have used it in cases where I needed to pass detached entity graphs back and forth.

For example:

// Update method of repository
public void Update(Order order)
{
    context.UpdateGraph(order, map => map
        .OwnedCollection(p => p.OrderItems);
}

The above would tell the Entity Framework to update the order entity and also merge the collection of OrderItems. Mapping in this fashion allows us to ensure that the Entity Framework only manages the graph within the bounds that we define on the aggregate and ignores all other properties. It supports optimistic concurrency checking of all entities. It handles much more complicated scenarios and can also handle updating references in many to many scenarios (via AssociatedCollections).

Hope this can be of use.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top