Finding Entity Framework contexts
Through various questions I have asked here and other forums, I have come to the conclusion that I have no idea what I'm doing when it comes to the generated entity context objects in Entity Framework.
As background, I have a ton of experience using LLBLGen Pro, and Entity Framework is about three weeks old to me.
Lets say I have a context called "myContext". There is a table/entity called Employee in my model, so I now have a myContext.Employees. I assume this to mean that this property represents the set of Employee entities in my context. However, I assume wrong, as I can add a new entity to the context with:
myContext.Employees.AddObject(new Employee());
and this new Employee entity appears nowhere in myContext.Employees. From what I gather, the only way to find this newly added entity is to track it down hiding in the myContext.ObjectStateManager. This sounds to me like the myContext.Employees set is in fact not the set of Employee entities in the context, but rather some kind of representation of the Employee entities 开发者_开发百科that exist in the database.
To add further to this confusion, Lets say I am looking at a single Employee entity. There is a Project entity that has a M:1 relationship with Employee (an employee can have multiple projects). If I want to add a new project to a particular employee, I just do:
myEmployee.Projects.Add(new Project());
Great, this actually adds the Project to the collection as I would expect. But this flies right in the face of how the ObjectSet properties off of the context work. If I add a new Project to the context with:
myContext.Projects.AddObject(new Project());
this does not alter the Projects set.
I would appreciate it very much if someone were to explain this to me. Also, I really want a collection of all the Employees (or Projects) in the context, and I want it available as a property of the context. Is this possible with EF?
An ObjectSet
is a query. Like everything in LINQ, it's lazy. It does nothing until you either enumerate it or call a method like .Count()
, at which point a database query is run, and any returned entities are merged with those already in the context.
So you can do something like:
var activeEmployees = Context.Employees.Where(e => e.IsActive)
...without running a query.
You can further compose this:
var orderedEmployees = activeEmployees.OrderBy(e => e.Name);
...again, without running a query.
But if you look into the set:
var first = orderedEmployees.First();
...then a DB query is run. This is common to all LINQ.
If you want to enumerate entities already in the context, you need to look towards the ObjectStateManager
, instead. So for Employees, you can do:
var states = EntityState.Added || EntityState.Deleted || // whatever you need
var emps = Context.ObjectStateManager.GetObjectStateEntries(states)
.Select(e => e.Entity)
.OfType<Employee>();
Note that although this works, it is not a way that I would recommend working. Typically, you do not want your ObjectContexts to be long-lived. For this, and other reasons, they are not really suitable to be a general-purpose container of objects. Use the usual List types for that. It is more accurate to think of an ObjectContext as a unit of work. Typically, in a unit of work you already know which instances you are working with.
精彩评论