How can we tell Entity Framework about Aggregates?
when saving an aggregate, save entities within the aggregate
when deleting an aggregate, delete entities within the aggregate
raise a concurrency error when two different users attempt to modify two different entities within the same aggreate
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)
EF provides features which allows you defining your aggregates and using them:
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.
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.
This is handled by concurrency tokens in the database - most commonly either timestamp or rowversion columns.
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).
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.
Related
I'm trying to understand how EntityFramework Core manages data internally because it influences how I call DbSets. Particularly, does it refer to in-memory data or re-query the database every time?
Example 1)
If I call _context.ToDo.Where(x => x.id == 123).First() and then in a different procedure call the same command again, will EF give me the in-memory value or re-query the DB?
Example 2)
If I call _context.ToDo.Where(x => x.id == 123).First() and then a few lines later call _context.ToDo.Find(123).Where(x => x.id == 123).Incude(x => x.Children).First(), will it use the in-memeory and then only query the DB for "Children" or does it recall the entire dataset?
I guess I'm wondering if it matters if I duplicate a call or not?
Is this affected by the AsNoTracking() switch?
What you really ask is how caching works in EF Core, not how DbContext manages data.
EF always offered 1st level caching - it kept the entities it loaded in memory, as long as the context remains alive. That's how it can track changes and save all of them when SaveChanges is called.
It doesn't cache the query itself, so it doesn't know that Where(....).First() is meant to return those specific entities. You'd have to use Find() instead. If tracking is disabled, no entities are kept around.
This is explained in Querying and Finding Entities, especially Finding entities using primary keys:
The Find method on DbSet uses the primary key value to attempt to find an entity tracked by the context. If the entity is not found in the context then a query will be sent to the database to find the entity there. Null is returned if the entity is not found in the context or in the database.
Find is different from using a query in two significant ways:
A round-trip to the database will only be made if the entity with the given key is not found in the context.
Find will return entities that are in the Added state. That is, Find will return entities that have been added to the context but have not yet been saved to the database.
In Example #2 the queries are different though. Include forces eager loading, so the results and entities returned are different. There's no need to call that a second time though, if the first entity and context are still around. You could just iterate over the Children property and EF would load the related entities one by one, using lazy loading.
EF will execute 1 query for each child item it loads. If you need to load all of them, this is slow. Slow enough to be have its own name, the N+1 selects problem. To avoid this you can load a related collection explicitly using explicit loading, eg. :
_context.Entry(todo).Collection(t=>t.Children).Load();
When you know you're going to use all children though, it's better to eagerly load all entities with Include().
I want to log exceptions to my database to ensure failures are recorded. I am using entity framework.
Should I setup an encapsulated logging service that records to a table which is not managed by entity framework or should I just make an ef class called Log?
Im thinking that a log is not really an entity that represents my application parts, but represents meta data which is why I ask.
Consider a separate (bounded) context for your general logging. If logs happen to reference top-level entities you can define minimal entity definitions for these as well. Logging operations are heavy-write, so by keeping a separate DbContext you minimize the spin-up time.
When it comes to auditing (I.e. persisting change tracking) then I commonly use a pattern that hooks directly into the DbContext events and records information based on when entities are updated, inserted, or deleted.
Using EF6.
I have a list of entity items that are detached from a dbContext. I'd like to explicit load several of the entities related to them, sometimes with through 2 or 3 levels of navigation.
I'd also like to do all this object graph loading in a single DB call if possible.
If its not possible with explicit loading techniques, I will just re-query the database for those specific item Ids and use eager loading at that point (since there is no other state I need to worry about at this point).
When I use Entity Framework, I want to query out a record in a context and add it to another context with the same schema, after query out the record, I detach it from the context, but the related entities are all away, is there any way to solve it?
Thanks in advance!
This is "by design". EF can detach entities only one by one but in the same time EF doesn't support object graphs composed of attached and detached entities. Because of that when you detach entity it will break all relations to the rest of attached object graph. Detaching whole object graph is currently not supported but you can vote for this feature on Data UserVoice.
As a workaround you can turn off lazy loading on your context, use eager loading described by #CodeWarrior to load exactly data you need to pass to other context. Once you have data loaded serialize them to stream and immediately deserialize them to the new instance of the object graph. This is the way how to make deep clone of entity graph which is detached but has all relations intact (turning lazy loading off is needed otherwise serialization will load all other navigation properties as well which can result in much bigger object graph then expected). The only requirement is that your entities must be serializable by serializer of your choice (be aware of circular references which usually require some special handling or additional attributes on your entities).
Are you asking how to load the child entities? If so, you can do eager loading with the .Include method. Given a Person class and a PhoneNumber class where Person has a collection of PhoneNumber, you could do the following:
List<Person> People = db.People.Where(p => p.Name = "Henry")
.Include("PhoneNumbers")
.ToList();
Or you can do what is called explicit loading where you load your entities and call the .Load method on the collections of child and related entities that you want to load. Generally you do this when you do not have LazyLoading enabled (and LazyLoading is enabled by default in 4.0+ don't recall in previous versions).
Regardless of how you query and load them, you will have to detach entities that you want to attach to a different context.
Here is a link to a pretty good MSDN article on loading entities.
For part of the project I'm currently working on, I have a set of four tables for syndicatable actions. One table is the abstract base for the other three, and each table is represented in my EF model like so:
EF Model -- Actions http://chris.charabaruk.com/system/files/images/EF+Model+Actions.png
There are two problems that I'm currently facing with this, however. The first problem is that Actor (a reference to a User) and Subject (a reference to an entity of the class associated with each type of action) are null in my subclasses, despite the associated database columns holding valid keys to rows in their associated tables. While I can get the keys via ActorReference and SubjectReference this of course requires setting up a new EF context and querying it for the referenced objects (as FooReference.Value is also null).
The second problem is that the reciprocal end of the relationship between the concrete action classes and their related entity classes always turn up nothing. For example, Task.RelatedActions, which should give me all TaskAction objects where Subject refers to the particular task object on which RelatedActions is called, is entirely devoid of objects. Again, valid rows exist in the database, Entity Framework just isn't putting them in objects and handing them to me.
Anyone know what it is I'm doing wrong, and what I should do to make it work?
Update: Seems that none of the relationship properties are working in my entity model any more, at all. WTF...
I think the issue you are experiencing here is that by default the EF does not automatically load related entities. If you load an entity, the collection or reference to related entities will be empty unless you do one of the following things:
1) Use eager loading in order to retrieve your main entity and your related entity in a single query. To do this, modify your query by adding a call to the Include method. In your sample above, you might use the following query:
from a in context.Actions.Include("Actor") select a
This would retrieve each of the actions with the related Actor method.
2) Use explicit lazy loading to retrieve the related entity when you need it:
action1.ActorReference.Load()
In the version of the EF which will ship with .Net 4.0, you will also have the following additional option:
3) Turn on implicit lazy loading so that related entities will automatically be retrieved when you reference the navigation property.
Danny