Getting newly added entities from ObjectContext before saving changes
OK, I read these:
EntityFramework show entities before saving changes
Where added objects are stored in ObjectContext?
I guess there is no clear solution of the problem (although the second post is from 2009) but I think it's an important issue of Entity Framework so I will ask my question despite all.
Let say we have code like that:
// Get somehow an UnitOfWork instance, e.g. using factory
var categoryRepository = new CategoryRepository(unitOfWork);
var newCategory = new Category("Some Category");
categoryRepository.Add(newCategory);
var allCategories = categoryRepository.GetAll();
Debug.Assert(allCategories.Contains(newCategory));
unitOfWork.Commit();
If we use NHibernate, the UnitOfWork implementation will encapsulate an ISession instance. And the given code will behave as we expect - we can get newly added category back from the repository (i.e. underlying ISession) before changes are committed.
I was surprised to discover that Entity Framework behave different. If our UnitOfWork implementation encapsulate EF's ObjectContext, the assertion fails. Before calling ObjectContext.SaveChages() (in the unitOfWork.Commit() method), newly added category is not reachable (via the same ObjectContext). I tried to find some property of ObjectContext that configure this behavior but didn't succeed.
So my question is: Is it possible to get entities from ObjectContext we just added without need of calling ObjectContext.SaveChages() (because we don't want to commit until the business transaction ends)? If the answer is "No", is not this violation of the Identity Map design pattern in particular and the UnitOfWork pattern in general? And if you use EF how deal with this scenarios?
Thanks in advance.
Sorry for the delay, guys.
It seems that you don't get my point. The question is not "How to get back this instance I've just added?" After all I have a reference to it. The question is "How does any newly added (still uncommitted - and actually it is possible never to be committed) entity to be considered by any query over the given DbSet?"
If I add a new category and then write something like that (I'm intentionally not using repository here but row DbContext (or ObjectContext if we are using EF 4.0) to be clearer to you):
var selectedCategories = context.Categories.Where(c => c.ParentCategory.Na开发者_开发问答me == "Some Category Name");
I want my new category to be returned in the result set if it satisfied the condition. Probably this query will be executed in another method (or even another class) that just share the same context (repository) within single transaction (unit of work). I know I can execute the same query over the Categories.Local, filter the result only to newly added entities (since Local contains all entities of the set that are currently being tracked) and combine it with result returned from the database. Don't you think it's terribly ugly? And I'm not even sure if I'm not missing something right now. All this is work of the ORM. It's all about transactional behavior (unit of work) and the ORM should handle it (like NHibernate does).
Now does it make sense to you?
精彩评论