EF 4.1 synchronises reverse associations when you create your instances. Is there any documentation of or best practices guidance available for this behaviour?
What I mean by synchronising the reverse association is that given:
public class Blog
{
public Blog() { Posts = new List<Blog>(); }
public int Id { get; set; }
public ICollection<Post> Posts { get; private set; }
}
public class Post
{
public Blog Blog { get; set; }
public int Id { get; set; }
}
Then after the following line the Post will have it's Blog property set.
var blog = new Blog();
context.Blogs.Add(blog);
blog.Posts.Add(new Post());
I believe - but I'm not sure - with "synchronising the reverse association" you mean a feature in Entity Framework which is called Relationship Fix-up or Relationship Span and is responsible to assign automatically navigation properties between objects in the ObjectContext. This is not specific to EF 4.1 but exists also for older versions.
I don't know a comprehensive documentation for this feature but here are a few resources which may give a bit more insight - especially the second one:
A brief definition: http://blogs.msdn.com/b/alexj/archive/2009/04/03/tip-10-understanding-entity-framework-jargon.aspx
A more detailed explanation (Zeeshan Hirani): http://www.daltinkurt.com/upload/dosyalar/file/Diger/entity_framework_learning_guide.pdf (Chapter 3.4 at page 125 - 133)
About situations where one wants to avoid relationship span: http://blogs.msdn.com/b/alexj/archive/2009/04/07/tip-11-avoiding-relationship-span.aspx
Edit
I am not able to give a comprehensive explanation of relationship span and all its impacts. But I can try to give a few examples where I feel safe that it's not completely wrong what I say:
In the answer you have linked in the comment Morteza makes a difference between entities which are derived from EntityObject
(only ObjectContext
in EF 4.0, not possible with DbContext
in EF 4.1) and POCOs (possible with ObjectContext
and DbContext
).
If you have POCOs then adding a new object to a navigation collection of another object which is already loaded into the context would not attach the new object to the context. This is not surprising because POCOs are, well..., POCOs, which means that they don't know anything about the EF context. Adding an object to a navigation collection is really nothing more than something like List<T>.Add(...)
. This generic Add
method doesn't do any operation on the EF context.
This is another situation with EntityObject
and EntityCollection
which both have references to the context internally and can therefore attach to the context immediately when you add to the collection.
One conclusion from this consideration is that the last code example in your question would not actually set the Blog
property in the Post
when you use POCOs. But: It will be set after you have called DetectChanges
or SaveChanges
(which calls DetectChanges
internally). In this situation DetectChanges
(which is probably a very complex method) looks into context what objects are there (it'll find the Blog
parent object) and then runs through the whole object graph (the Posts
collection in our case) and checks if the other objects in the graph (the Post
objects) are also in the context. If not - and this is the case in your example - it will attach them to the context in Added
state and - here comes relationship span into play now - also fix the navigation properties in the object graph.
Another situation where relationship span also acts with POCOs is when you load objects into the context.
For example: If you have a Blog
with id = x and a Post
with id = y which belongs to this Blog
in the database then this code ...
var blog = context.Blogs.Find(x); // no eager loading of the Posts collection!
var post = context.Posts.Find(y); // no eager loading of the Blog property!
would automatically build up the navigation properties in each object, so the Posts
collection of the Blog
will suddenly contain the post and the Blog
property in Post
will refer to the blog. This relationship fix-up depends on the fact that the objects are indeed loaded into the context. If you suppress this by using AsNoTracking
for example ...
var blog = context.Blogs.AsNoTracking().Where(b => b.Id == x).Single();
var post = context.Posts.AsNoTracking().Where(p => p.Id == y).Single();
... relationship span doesn't work and the navigation properties will stay null
.
A last note: Relationship span - as in the example above - only works if the assocation on at least one end has a cardinality of 0...1
(one-to-one or one-to-many associations). It never works for many-to-many associations. This was recently discussed here (with EF 4.1): EF 4.1 loading filtered child collections not working for many-to-many
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With