I get the error : “An entity object cannot be referenced by multiple instances of IEntityChangeTracker.” with .net MVC2 and the Entity Framework4 - entity-framework

I have a big problem since some days and I’m a very beginner in the Entity Framework.
I have 2 entities : Group and News. A news is visible by one or many groups. I use two repositories (newsRepository and groupsRepository).
This is my Create method for the news :
public ActionResult Create()
{
return View(new CreateNewsViewModel(new News()));
}
[HttpPost]
public ActionResult Create(CreateNewsViewModel model)
{
model.news.CategoryId = Int32.Parse(Request.Form["news.CategoryId"]);
if (ModelState.IsValid)
{
News news = new News();
DateTime date = DateTime.Now;
//AuthorId a recuperer
news.AuthorId = 1;
news.Title = IntranetTools.UppercaseFirst(model.news.Title.Trim());
news.Content = model.news.Content;
news.IsVisible = Request.Form["news.IsVisible"].Contains("true");
news.CreateDate = date;
news.PublicationDate = date;
news.LastChangedDate = date;
news.CategoryId = model.news.CategoryId;
// Collection des groupes concernés
foreach (var c in model.allGroups)
{
if (Request.Form["" + c.GroupId].Contains("true"))
{
News.Groups.Add(c);
}
}
_newsRepository.AddToNewsSet(news);
_newsRepository.SaveChanges();
return Redirect("/NewsAdmin/Index/");
}
return View(model);
}
I say that all my groups are already created. I just want to insert the groups (chosen by the user via checkboxes). In my “CreateNewsViewModel”, I create a list of groups that contains all existing groups in my DB. I get the list in my view, via a “foreach” loop and create a checkbox for each group.
I reuse the same list in my controller to compare if checkboxes have been checked.
For each “true” value, I add groups in the groups collection of my news (just created).
With this, I get this Error Message :
“An entity object cannot be referenced by multiple instances of IEntityChangeTracker.” (at line _newsRepository.AddToNewsSet(news);)
I try some solutions but I still don’t understand how I can solve this problem.
Thanks for all
Edit
Actually, if I use explicitly two contexts and detach/attach my objects to other context it's fine and I have no erros.
ObjectContext context = _newsRepository.Context;
ObjectContext context2 = _groupsRepository.Context;
foreach (var c in groups)
{
if (Request.Form["" + c.GroupId].Contains("true"))
{
context2.Detach(c);
context.Attach(c);
news.Groups.Add(c);
}
}
I would like to use the Ladislav Mrnka's solution and use the dependency injection (I use Ninject framework) to give the same ObjectContext to my repositories (in single request processing).
I understand the concept but I don't know how to code it.

The error message says that News object or any of related Group objects is attached to different ObjectContext instance. How is your repository implemented and how did you get model.allGroups? If you loaded allGroups from GroupsRepository which has its own ObjectContext instance then it is probably source of the problem. The solution would be:
(Preferred) Share single ObjectContext for all repositories in single request processing
Detach objects when you load them from database (ObjectContext has Detach method)
Close ObjectContext when you load objects from database

Related

How to find all managed attached objects in EntityManager (JPA)

Is there a way to get all objects which are currently attached in the entity manager?
I want to write some monitoring code which will report the number of attached objects and their classes.
Meaning finding all objects which were loaded by previous queries and find operations into the entity manager.
I'm using EclipseLink, so a specific solution is good too.
EclipseLink's JPA interface pretty much wraps its native code such that an EntityManager uses a UnitOfWork session underneath (and the EMF wraps a ServerSession). You need to get at the UnitOfWork if you want to see what entities it is managing.
If using JPA 2.0, you can use the EntityManager unwrap method:
UnitOfWork uow = em.unwrap(UnitOfWork.class);
otherwise, use some casting
UnitOfWork uow = ((EntityManagerImpl)em).getUnitOfWork();
From there, the UnitOfWork has a list of all registered (aka managed) entities. You can use the UOW to directly log what it has using the printRegisteredObjects() method, or obtain it yourself using getCloneMapping().keySet().
You can also see deleted objects by using hasDeletedObjects() and then getDeletedObjects().keySet() if there are any, as and the same for new objects using hasNewObjectsInParentOriginalToClone() and getNewObjectsCloneToOriginal().keySet()
you can use JPA in a lot of ways i am still unaware of, and there is a lot going on under the hood in eclipselink that i still do not fully understand, but it looks like it is possible to see into the persistence context. USE THIS CODE AT YOUR OWN RISK. it is only meant to give you a hint that it is possible to inspect the context. (whether the code is right or wrong i'm posting it because it would have helped me when i was trying to decide whether to use eclipselink. there doesn't seem to be much in the way of documentation about how to do this properly.)
public void saveChanges() {
Date now = new Date();
JpaEntityManager jem = em.unwrap(JpaEntityManager.class);
UnitOfWorkImpl uow = jem.unwrap(UnitOfWorkImpl.class);
// inserts
for (Object entity : uow.getNewObjectsCloneToOriginal().keySet()) {
if (entity instanceof IAuditedEntity) {
IAuditedEntity auditedEntity = (IAuditedEntity) entity;
auditedEntity.setAuditedUserId(this.userId);
auditedEntity.setAuditedAt(now);
auditedEntity.setCreatedAt(now);
}
}
// updates
UnitOfWorkChangeSet uowChangeSet = (UnitOfWorkChangeSet) uow.getUnitOfWorkChangeSet();
if (uowChangeSet != null) {
List<IAuditedEntity> toUpdate = new ArrayList<>();
for(Entry<Object, ObjectChangeSet> entry : uowChangeSet.getCloneToObjectChangeSet().entrySet()) {
if (entry.getValue().hasChanges()) {
if (entry.getKey() instanceof IAuditedEntity) {
toUpdate.add((IAuditedEntity) entry.getKey());
}
}
}
for (IAuditedEntity auditedEntity : toUpdate) {
auditedEntity.setAuditedUserId(this.userId);
auditedEntity.setAuditedAt(now);
}
}
// deletions
Project jpaProject = uow.getProject();
boolean anyAuditedDeletions = false;
for (Object entity : uow.getDeletedObjects().keySet()) {
if (entity instanceof IAuditedEntity) {
anyAuditedDeletions = true;
DeletedEntity deletion = new DeletedEntity();
deletion.setTableName(jpaProject.getClassDescriptor(entity.getClass()).getTableName());
deletion.setEntityId(((IAuditedEntity) entity).getId());
deletion.setAuditedUserId(this.userId);
em.persist(deletion);
}
}
}
You can achieve this by inspecting the entities on MetaModel which can be obtained from any EntityManager.
Example usage:
EntityManager em = // get your EM however...
for(EntityType<?> entityType : em.getMetaModel().getEntities())
{
Class<?> managedClass = entityType.getBindableJavaType();
System.out.println("Managing type: " + managedClass.getCanonicalName());
}
This example will print out all of the class types being managed by the EntityManager. To get all of the actual objects being managed, simply query all objects of that type on the EntityManager.
Update:
As of JPA 2.0 you can cache results that will be managed by javax.persistence.Cache. However, with plain JPA there is no way to actually retrieve the objects stored in the cache, the best you can do is check if a certain object is in the Cache via Cache.contains(Class cls, Object pk):
em.getEntityManagerFactory().getCache().contains(MyData.class, somePK);
However, EclipseLink extends Cache with JpaCache. You can use this to actually get the object from the cache via JpaCache.getObject(Class cls, Object id). This doesn't return a collection or anything, but it's the next best thing.
Unfortunately, if you want to actually access objects in the cache, you will need to manage this yourself.
I dont see such an option in the EntityManager interface. There is only a contains(Object entity) method but you need to pass the conrete objects and they are the checked for existentnce in the PersistenceContext. Also looking at the PersistenceContext interface i dont see such an option.

How can I create a generic update method for One to Many structures in Entity Framework 5?

I am writing a web application, such that I get different objects back from the web that need to be either updated or added to the database. On top of this, I need to check that the owner is not modified. Since a hacker could potentially get an account and send an update to modify the foreign key to the user model. I don't want to have to manually code all of these methods, instead I want to make a simple generic call.
Maybe something as simple as this
ctx.OrderLines.AddOrUpdateSet(order.OrderLines, a => a.Order)
Based on old persisted records that have a foreign key to Order, and on the new incoming records.
Delete old records that are not on the new records list.
Add new records that are not on the old records list.
Update new records that exist on both lists.
ctx.Entry(orderLine).State=EntityState.Deleted;
...
ctx.Entry(orderLine).State=EntityState.Added;
...
ctx.Entry(orderLine).State=EntityState.Modified;
This gets a bit complicated when the old record is loaded to verify that ownership did not change. I get an error if I don't do.
oldorder.OrderLines.remove(oldOrderLine); //for deletes
oldorder.OrderLines.add(oldOrderLine); //for adds
ctx.Entry(header).CurrentValues.SetValues(header); //for modifications
With Entity Framework 5 there is a new extension function called AddOrUpdate. And there was a very interesting (please read) blog entry on how to create this method before it was added.
I'm not sure if this is too much to ask as a question in StackOverflow, any clues on how to approach the problem may be sufficient. Here are my thoughts so far:
a) leverage AddOrUpdate for some of the functionality.
b) create a secondary context hoping to avoid loading order into the context and avoid extra calls.
c) Set the state of all the saved objects to initially deleted.
Since you have linked to this question from my own question, I thought I'd throw in some newly-aquired experience with Entity Framework for me.
To achieve a common save method in my generic repository with Entity Framework, I do this. (Please note that the Context is a member of my repository, as I am implementing the Unit of Work pattern as well)
public class EFRepository<TEntity> : IRepository<TEntity> where TEntity : class
{
internal readonly AwesomeContext Context;
internal readonly DbSet<TEntity> DbSet;
public EFRepository(AwesomeContext context)
{
if (context == null) throw new ArgumentNullException("context");
Context = context;
DbSet = context.Set<TEntity>();
}
// Rest of implementation removed for brevity
public void Save(TEntity entity)
{
var entry = Context.Entry(entity);
if (entry.State == EntityState.Detached)
DbSet.Add(entity);
else entry.State = EntityState.Modified;
}
}
Honestly, I can't tell you why this works, because I just kept changing the state conditions - however I do have unit (integration) tests to prove that it works. Hopefully someone more into EF than myself can shed some light on this.
Regarding the "cascading updates", I was curious myself as if it would work using the Unit of Work pattern (my question I linked to was when I did not know it existed, and my repositories would basically create a unit of work whenever I wanted to save/get/delete, which is bad), so I threw in a test case in a simple relational DB. Here is a diagram to give you an idea.
IMPORTANT In order for test case number 2 to work, you need to make your POCO reference properties virtual, in order for EF to provide lazy loading.
The repository implementation is just derived from the generic EFRepository<TEntity> as shown above, so I'll leave out that implementation.
These are my test cases, both pass.
public class EFResourceGroupFacts
{
[Fact]
public void Saving_new_resource_will_cascade_properly()
{
// Recreate a fresh database and add some dummy data.
SetupTestCase();
using (var ctx = new LocalizationContext("Localization.CascadeTest"))
{
var cultureRepo = new EFCultureRepository(ctx);
var resourceRepo = new EFResourceRepository(cultureRepo, ctx);
var existingCulture = cultureRepo.Get(1); // First and only culture.
var groupToAdd = new ResourceGroup("Added Group");
var resourceToAdd = new Resource(existingCulture,"New Resource", "Resource to add to existing group.",groupToAdd);
// Verify we got a single resource group.
Assert.Equal(1,ctx.ResourceGroups.Count());
// Saving the resource should also add the group.
resourceRepo.Save(resourceToAdd);
ctx.SaveChanges();
// Verify the group was added without explicitly saving it.
Assert.Equal(2, ctx.ResourceGroups.Count());
}
// try creating a new Unit of Work to really verify it has been persisted..
using (var ctx = new LocalizationContext("Localization.CascadeTest"))
{
Assert.DoesNotThrow(() => ctx.ResourceGroups.First(rg => rg.Name == "Added Group"));
}
}
[Fact]
public void Changing_existing_resources_group_saves_properly()
{
SetupTestCase();
using (var ctx = new LocalizationContext("Localization.CascadeTest"))
{
ctx.Configuration.LazyLoadingEnabled = true;
var cultureRepo = new EFCultureRepository(ctx);
var resourceRepo = new EFResourceRepository(cultureRepo, ctx);
// This resource already has a group.
var existingResource = resourceRepo.Get(2);
Assert.NotNull(existingResource.ResourceGroup); // IMPORTANT: Property must be virtual!
// Verify there is only one resource group in the datastore.
Assert.Equal(1,ctx.ResourceGroups.Count());
existingResource.ResourceGroup = new ResourceGroup("I am implicitly added to the database. How cool is that?");
// Make sure there are 2 resources in the datastore before saving.
Assert.Equal(2, ctx.Resources.Count());
resourceRepo.Save(existingResource);
ctx.SaveChanges();
// Make sure there are STILL only 2 resources in the datastore AFTER saving.
Assert.Equal(2, ctx.Resources.Count());
// Make sure the new group was added.
Assert.Equal(2,ctx.ResourceGroups.Count());
// Refetch from store, verify relationship.
existingResource = resourceRepo.Get(2);
Assert.Equal(2,existingResource.ResourceGroup.Id);
// let's change the group to an existing group
existingResource.ResourceGroup = ctx.ResourceGroups.First();
resourceRepo.Save(existingResource);
ctx.SaveChanges();
// Assert no change in groups.
Assert.Equal(2, ctx.ResourceGroups.Count());
// Refetch from store, verify relationship.
existingResource = resourceRepo.Get(2);
Assert.Equal(1, existingResource.ResourceGroup.Id);
}
}
private void SetupTestCase()
{
// Delete everything first. Database.SetInitializer does not work very well for me.
using (var ctx = new LocalizationContext("Localization.CascadeTest"))
{
ctx.Database.Delete();
ctx.Database.Create();
var culture = new Culture("en-US", "English");
var resourceGroup = new ResourceGroup("Existing Group");
var resource = new Resource(culture, "Existing Resource 1",
"This resource will already exist when starting the test. Initially it has no group.");
var resourceWithGroup = new Resource(culture, "Exising Resource 2",
"Same for this resource, except it has a group.",resourceGroup);
ctx.Cultures.Add(culture);
ctx.ResourceGroups.Add(resourceGroup);
ctx.Resources.Add(resource);
ctx.Resources.Add(resourceWithGroup);
ctx.SaveChanges();
}
}
}
It was interesting to learn this, as I was not sure if it would work.
After working on this for a while I found an opensource project called GraphDiff here is it's blog entry 'introducing graphdiff for entity framework code first – allowing automated updates of a graph of detached entities'. I only began using it but it looks impressive. And it does solve the problem of issuing update/delete/insert for Many to One relationships. It actually generalizes the problem to graphs and allows arbitrary nesting.
Here is the generic method I concocted. It does use AddOrUpdate from the System.Data.Entity.Migrations namespace. Which may be reloading records from the db, I'll be checking on that later. The usage is
ctx.OrderLines.AddOrUpdateSet(l => l.orderId == neworder.Id,
l => l.Id, order.orderLines);
Here is the code:
public static class UpdateExtensions
{
public static void AddOrUpdateSet<TEntity>(this IDbSet<TEntity> set, Expression<Func<TEntity, bool>> predicate,
Func<TEntity, int> selector, IEnumerable<TEntity> newRecords) where TEntity : class
{
List<TEntity> oldRecords = set.Where(predicate).ToList();
IEnumerable<int> keys = newRecords.Select(selector);
foreach (TEntity newRec in newRecords)
set.AddOrUpdate(newRec);
oldRecords.FindAll(old => !keys.Contains(selector(old))).ForEach(detail => set.Remove(detail));
}
}

MVC 2 and EF4 Self-tracking entities models have bad state on post back

I've got standard Create() Edit() and Delete() methods on my controllers, and I am using the EF4 Self-tracking entities.
When the edit is posted back, the model.ChangeTracker.ChangeTracking = false, and model.ChangeTracker.State = ObjectState.Added, even though I made sure those are set when retrieving the record initially.
Are the self-tracking entities not persisting the ChangeTracker class when the form is submitted? If so, how do I fix that?
public virtual ActionResult Edit(int personId)
{
IContext context = ContextFactory.GetContext();
EntityRepo Repo = new EntityRepo(context);
Person d = Repo.Person.GetById(PersonId);
d.ChangeTracker.ChangeTrackingEnabled = true;
return View(d);
}
[HttpPost]
public virtual ActionResult Edit(int personId, Person item)
{
try
{
if (ModelState.IsValid)
{
IContext context = ContextFactory.GetContext();
EntityRepo Repo = new EntityRepo(context);
// the item is returning these properties that are wrong
//item.ChangeTracker.ChangeTrackingEnabled = false;
//item.ChangeTracker.State = ObjectState.Added;
Repo.Person.Update(item);
Repo.Person.SaveChanges();
return RedirectToAction("Index");
}
}
catch
{
}
return View();
}
Let's start at the beginning.
What are Self-Tracking Entities, exactly?
A Self-Tracking Entity is an entity which can do change tracking even when it is not connected to a ObjectContext. They are useful in times when you must change the entity, but cannot have it connected to an ObjectContext.
So when would I want one, really?
Mostly, when you must have distributed objects. For example, one use case is when you are making a web service which talks to a Silverlight client. However, other tools, like RIA Services may be a better fit here. Another possible use case is for a long-running task. Since an ObjectContext is intended to be a unit of work and should typically not be long-lived, having a disconnected entity might make sense here.
Do they make any sense for MVC?
Not really, no.
Let's look at this a little deeper, and examine what happens when you update an entity in MVC. The general process is like this:
The browser issues a GET request for an update page.
The MVC app fetches an entity, and uses it to build an update HTML page. The page is served to the browser, and most C# objects, including your entity, are disposed. At this point, you can restart the Web server, and the browser will never know the difference.
The browser issues a POST request to update the entity.
The MVC framework uses the data in the POST in order to materialize an instance of an edit model which is passed to the update action. This might happen to be the same type as the entity, but it is a new instance.
The MVC app can update the entity and pass those changes back to the database.
Now, you could make self-tracking entities work by also including the full state of the STE in the HTML form and POSTing that back to the MVC app along with the scalar values on the entity. Then the Self-Tracking Entity might at least work.
But what benefit does this give you? The browser obviously cannot deal with your entity as a C# object. So it cannot make any changes to the entity worth tracking in terms that a Self-Tracking Entity would understand.
U should keep original STE in some hidden field. It's like your custom ViewState. In submit method u must merge original STE and new values.
Use ActionFilterAttribute for it.
Like
public class SerializeOriginalModelAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
var viewResult = filterContext.Result as ViewResult;
if (viewResult == null)
return;
var viewModel = viewResult.ViewData.Model as ViewModel;
if (viewModel == null || viewModel.SteObject == null)
return;
byte[] bytes;
using (var stream = new MemoryStream())
{
var serializer = new DataContractSerializer(viewModel.SteObject.GetType());
serializer.WriteObject(stream, viewModel.SteObject);
bytes = stream.ToArray();
}
var compressed = GZipHelper.Compress(bytes);
viewModel.SerializedSteObject = Convert.ToBase64String(compressed);
}
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.ActionParameters == null || filterContext.ActionParameters.Count == 0)
return;
var viewModel = filterContext.ActionParameters.First().Value as ViewModel;
var serialized = filterContext.HttpContext.Request.Form["SerializedSteObject"];
if (viewModel == null || String.IsNullOrEmpty(serialized))
return;
var type = filterContext.ActionParameters.First().Value.GetType().BaseType.GetGenericArguments()[0];
var bytes = GZipHelper.Decompress(Convert.FromBase64String(serialized));
using (var stream = new MemoryStream(bytes))
{
var serializer = new DataContractSerializer(type);
viewModel.SteObject = serializer.ReadObject(stream);
}
}
}
STE has one very big drawback. You have to store them in session or view state (WebForms). So it is nothing more than "new version of dataset". If you don't store STE you will have one instance for getting data and different for posting = no change tracking.
I think you are missing the idea of Repository. You should not have an Update method in the Repository. After submitting, you should get the item again, apply the modifications and then Save.
I prefer having a service layer between client and Repository. We can always change the strategy with which we merge.
And yes, if you need to persist your STE's between requests, use session or viewstate.
It should be
Repo.Person.ApplyChanges(item);
Repo.Person.SaveChanges();
instead of
Repo.Person.Update(item);
Repo.Person.SaveChanges();
Self Tracking works with ApplyChanges extention method.

Entity Framework and Entity Tracker Problems

If I run the following code it throws the following error:
An entity object cannot be referenced by multiple instances of IEntityChangeTracker
public void Save(Category category)
{
using(var db = new NorthwindContext())
{
if(category.CategoryID == 0)
{
db.AddToCategorySet(category);
}
else
{
//category.RemoveTracker();
db.Attach(category);
}
db.SaveChanges();
}
}
The reason is of course that the category is sent from interface which we got from GetById method which already attached the EntityChangeTracker to the category object. I also tried to set the entity tracker to null but it did not update the category object.
protected void Btn_Update_Category_Click(object sender, EventArgs e)
{
_categoryRepository = new CategoryRepository();
int categoryId = Int32.Parse(txtCategoryId.Text);
var category = _categoryRepository.GetById(categoryId);
category.CategoryName = txtUpdateCategoryName.Text;
_categoryRepository.Save(category);
}
I'm still learning Entity Framework myself, but maybe I can help a little. When working with the Entity Framework, you need to be aware of how you're handling different contexts. It looks like you're trying to localize your context as much as possible by saying:
public void Save(Category category)
{
using (var db = new NorthwindContext())
{
...
}
}
... within your data access method. Did you do the same thing in your GetById method? If so, did you remember to detach the object you got back so that it could be attached later in a different context?
public Category GetById(int categoryId)
{
using (var db = new NorthwindContext())
{
Category category = (from c in db.Category where Category.ID == categoryId select c).First();
db.Detach(category);
}
}
That way when you call Attach it isn't trying to step on an already-attached context. Does that help?
As you pointed out in your comment, this poses a problem when you're trying to modify an item and then tell your database layer to save it, because once an item is detached from its context, it no longer keeps track of the changes that were made to it. There are a few ways I can think of to get around this problem, none of them perfect.
If your architecture supports it, you could expand the scope of your context enough that your Save method could use the same context that your GetById method uses. This helps to avoid the whole attach/detach problem entirely, but it might push your data layer a little closer to your business logic than you would like.
You can load a new instance of the item out of the new context based on its ID, set all of its properties based on the category that is passed in, and then save it. This costs two database round-trips for what should really only need one, and it isn't very maintainable.
You can dig into the context itself to mark the Category's properties as changed.
For example:
public void Save(Category category)
{
using (var db = new NorthwindContext())
{
db.Attach(category);
var stateEntry = db.ObjectStateManager.GetObjectStateEntry(category);
foreach (var propertyName in stateEntry.CurrentValues.DataRecordInfo.FieldMetadata.Select(fm => fm.FieldType.Name)) {
stateEntry.SetModifiedProperty(propertyName);
}
db.SaveChanges();
}
}
This looks a little uglier, but should be more performant and maintainable overall. Plus, if you want, you could make it generic enough to throw into an extension method somewhere so you don't have to see or repeat the ugly code, but you still get the functionality out of it.

Convince entity context (EF1) to populate entity references

I have an entity with self reference (generated by Entity Designer):
public MyEntity: EntityObject
{
// only relevant stuff here
public int Id { get...; set...; }
public MyEntity Parent { get...; set...; }
public EntityCollection<MyEntity> Children { get...; set...; }
...
}
I've written a stored procedure that returns a subtree of nodes (not just immediate children) from the table and returns a list of MyEntity objects. I'm using a stored proc to avoid lazy loading of an arbitrary deep tree. This way I get relevant subtree nodes back from the DB in a single call.
List<MyEntity> nodes = context.GetSubtree(rootId).ToList();
All fine. But when I check nodes[0].Children, its Count equals to 0. But if I debug and check context.MyEntities.Results view, Children enumerations get populated. Checking my result reveals children under my node[0].
How can I programaticaly force my entity context to do in-memory magic and put correct references on Parent and Children properties?
UPDATE 1
I've tried calling
context.Refresh(ClientWins, nodes);
after my GetSubtree() call which does set relations properly, but fetches same nodes again from the DB. It's still just a workaround. But better than getting the whole set with context.MyEntities().ToList().
UPDATE 2
I've reliably solved this by using EF Extensions project. Check my answer below.
You need to assign one end of the relationship. First, divide the collection:
var root = nodes.Where(n => n.Id == rootId).First();
var children = nodes.Where(n => n.Id != rootId);
Now, fix up the relationship.
In your case, you'd do either:
foreach (var c in children)
{
c.Parent = root;
}
...or:
foreach (var c in children)
{
root.Children.Add(c);
}
It doesn't matter which.
Note that this marks the entities as modfied. You'll need to change that if you intend to call SaveChanges on the context and don't want this saved.
The REAL solution
Based on this article (read text under The problem), navigation properties are obviously not populated/updated when one uses stored procedures to return data.
But there's a nice manual solution to this. Use EF Extensions project and write your own entity Materilizer<EntityType> where you can correctly set navigation properties like this:
...
ParentReference = {
EntityKey = new EntityKey(
"EntityContextName.ParentEntitySetname",
new[] {
new EntityKeyMember(
"ParentEntityIdPropertyName",
reader.Field<int>("FKNameFromSP")
)
})
}
...
And that's it. Calling stored procedure will return correct data, and entity object instances will be correctly related to eachother. I advise you check EF Extensions' samples, where you will find lots of nice things.