Is the Entity Framework ObjectContext the correct implementation of the Unit of Work pattern?

Entity Framework 4 - STE - a simple single-table database Blogs that have a column column BlogID ...

var samplesDbEntities = new SamplesDBEntities(); var blogId = Guid.NewGuid(); samplesDbEntities.Blogs.AddObject(new Blog() { BlogID = blogId }); var objectSetResult = samplesDbEntities.Blogs .Where(p => p.BlogID == blogId) .SingleOrDefault(); 

(code execution result => objectSetResult == null after the last line)

AFAIK, ObjectContext is an implementation of the UoW template, and in this case, I think I should return the result from the ObjectSet (repository), just “marked as transient,” Can someone explain to me what I'm doing wrong and why objectSetResult has zero value here?

(Yes, I know ObjectStateManager, but for me it is more of a patch for the aforementioned architectural problem)

+6
entity-framework entity-framework-4
source share
3 answers

A template violation in your example is not a work template, but a mapping of identifiers.

Changes in the work of the working group made to the objects according to your code, and not to take care of it manually.

An identifier mapping template introduces an object context to have an instance of a single object for a single primary key value.

This is strange for me, but the Entity Framework (as well as LINQ 2 SQL) does not display the identity of the object in each situation, and the situation described above is one such case.

+1
source share

You need to call

 samplesDbEntities.SaveChanges(); 

before the request for the object.

 var samplesDbEntities = new SamplesDBEntities(); var blogId = Guid.NewGuid(); samplesDbEntities.Blogs.AddObject(new Blog() { BlogID = blogId }); samplesDbEntities.SaveChanges(); var objectSetResult = samplesDbEntities.Blogs .Where(p => p.BlogID == blogId) .SingleOrDefault(); 

Update

The reason you don't get the added user back to objectSetResult is because calling the SingleOrDefault method of the IQueryable object leads to a database query (the actual SQL query string is generated according to the "where" condition, etc.)., And since the object is not yet installed in the database, it is not returned. However, the new object is context bound, and EntityState is set to Added. According to MSDN, objects in the added state do not have the original values ​​in the ObjectStateEntry. The state of objects within an object context is controlled by the ObjectStateManager. Therefore, if you want to check if the object is really connected, you can get it by calling GetObjectStateEntry:

 var samplesDbEntities = new SamplesDBEntities(); Blog blog = new Blog() { BlogID = Guid.NewGuid() }; samplesDbEntities.Blogs.AddObject("Blogs", blog); Blog addedBlog = (Blog)context.ObjectStateManager.GetObjectStateEntry(blog).Entity; 

Also note that the EntityState of the retrieved object is "Added."

To summarize - regarding your initial question as to whether this is the correct implementation of UnitOfWork, I don't understand why not. It really maintains a list of objects and tracks changes, etc. Etc. However, the problem you are facing is related to the fact that you are retrieving data from the primary provider, and not from the list of objects that are currently connected to the context.

+4
source share

Thank you for clarifying your point. I add this as another answer, because there is little to say about this.

AFAIK, there is no strict universal definition of UoW, so the topic is discussed of course. My scores are as follows:

  • You are adding an object to the context, but trying to extract it from db. The conclusion that the ObjectContext is not a valid UoW implementation is illogical.

  • If you add entities to the context in order to later display them for some reason before saving changes to db, you do not use EF, since it is intended for use. Generally, you should not use an ObjectStateManager for this, but you can:

     Blog addedBlog = context. ObjectStateManager. GetObjectStateEntries(EntityState.Added). Where(ent => (ent.Entity is Blog) && ((Blog)ent.Entity).BlogID == blogID). Select(ent => ent.Entity as Blog). SingleOrDefault(); 
  • A unit of work is a context object that maintains lists of business objects, tracks changes in their state during a single business transaction. Does EF support ObjectContext? Yes. Does it provide reasonable syntax for retrieving an object that is in the Added state? No, but this is not a requirement for a “correct” UoW implementation. Remember that EF is an ORM, and the goal is to track changes in your db in your code, not changes between different parts of your code (for which you have your business logic).

And with regard to: "What is the point of UoW, if I have to persist every object by itself, and not in a package" - the fact is that you can add a bunch of objects to the context, and then save them all at once by calling SaveChanges. As I mentioned, the context is not intended to be used to migrate your business objects. However, you can retrieve them from the ObjectStateManager without constantly changing the database if you want.

0
source share

All Articles