Print Page | Close Window

Is there a multiple entity manager demo?

Printed From: IdeaBlade
Category: DevForce
Forum Name: DevForce 2010
Forum Discription: For .NET 4.0
URL: http://www.ideablade.com/forum/forum_posts.asp?TID=2149
Printed Date: 29-Jul-2026 at 4:17am


Topic: Is there a multiple entity manager demo?
Posted By: hueha
Subject: Is there a multiple entity manager demo?
Date Posted: 11-Sep-2010 at 12:39pm
Is there a demo that shows how to implement multiple entity managers?

I am really struggling to get the multiple entity manager working.  I've been working off the code posted at http://drc.ideablade.com/xwiki/bin/view/Documentation/SavingBusinessObjects#HDependencyGraphRetrieval

However, I'm not sure how to implement the step that says 
"After save, the application might export the saved rep back into the main EM where it now displays in the grid in its post-save glory http://drc.ideablade.com/xwiki/bin/view/Documentation/SavingBusinessObjects#x_footnote_12 - 12 ."

It seems when I call SaveChangesAsync on the second entity model it is not being committed to the database.  So I basically used the dependency graph retrieval in reverse to get the models back into the main EM.  Some issues I have found are

1) The dependency graph is not picking up items which are still being loaded asynchronously
3) Doesn't like many to many relationships.   I get this error when trying to save
{EntityManagerSaveException: The object being attached to the source object is not attached to the same ObjectContext as the source object. ---> System.InvalidOperationException: The object being attached to the source object is not attached to the same ObjectContext as the source object.
   at System.Data.Objects.DataClasses.RelatedEnd.ValidateEntityForAttach(IEntityWrapper wrappedEntity, Int32 index, Boolean allowCollection)
   at System.Data.Objects.DataClasses.RelatedEnd.Attach(IEnumerable`1 wrappedEntities, Boolean allowCollection)
   at System.Data.Objects.DataClasses.RelatedEnd.System.Data.Objects.DataClasses.IRelatedEnd.Attach(Object entity)
   at IdeaBlade.EntityModel.Edm.EdmSaveHelper.ProcessManyToMany(List`1 entities)
   at IdeaBlade.EntityModel.Edm.EdmSaveHelper.ProcessSaves(IEnumerable`1 groupsByType)
   at IdeaBlade.EntityModel.Edm.EdmSaveHelper.SaveWithinContext()
   at IdeaBlade.EntityModel.Edm.EdmSaveHelper.Save()
   at IdeaBlade.EntityModel.EntityManager.HandleEntityServerException(Exception pException, Boolean pTryToHandle, PersistenceOperation pOperation)
   at IdeaBlade.EntityModel.EntityManager.HandleSaveResultException(SaveWorkState saveWorkState, Boolean isAsyncOp)}
    [IdeaBlade.EntityModel.EntityManagerSaveException]: {EntityManagerSaveException: The object being attached to the source object is not attached to the same ObjectContext as the source object. ---> System.InvalidOperationException: The object being attached to the source object is not attached to the same ObjectContext as the source object.
   at System.Data.Objects.DataClasses.RelatedEnd.ValidateEntityForAttach(IEntityWrapper wrappedEntity, Int32 index, Boolean allowCollection)
   at System.Data.Objects.DataClasses.RelatedEnd.Attach(IEnumerable`1 wrappedEntities, Boolean allowCollection)
   at System.Data.Objects.DataClasses.RelatedEnd.System.Data.Objects.DataClasses.IRelatedEnd.Attach(Object entity)
   at IdeaBlade.EntityModel.Edm.EdmSaveHelper.ProcessManyToMany(List`1 entities)
   at IdeaBlade.EntityModel.Edm.EdmSaveHelper.ProcessSaves(IEnumerable`1 groupsByType)
   at IdeaBlade.EntityModel.Edm.EdmSaveHelper.SaveWithinContext()
   at IdeaBlade.EntityModel.Edm.EdmSaveHelper.Save()
   at IdeaBlade.EntityModel.EntityManager.HandleEntityServerException(Exception pException, Boolean pTryToHandle, PersistenceOperation pOperation)
   at IdeaBlade.EntityModel.EntityManager.HandleSaveResultException(SaveWorkState saveWorkState, Boolean isAsyncOp)}
    Data: {System.Collections.ListDictionaryInternal}
    InnerException: null
    Message: "The object being attached to the source object is not attached to the same ObjectContext as the source object."
    StackTrace: "   at IdeaBlade.EntityModel.EntityManager.HandleEntityServerException(Exception pException, Boolean pTryToHandle, PersistenceOperation pOperation)\r\n   at IdeaBlade.EntityModel.EntityManager.HandleSaveResultException(SaveWorkState saveWorkState, Boolean isAsyncOp)"





Replies:
Posted By: sbelini
Date Posted: 20-Sep-2010 at 6:10pm
Hi,
 
you asked:
However, I'm not sure how to implement the step that says 
"After save, the application might export the saved rep back into the main EM where it now displays in the grid in its post-save glory http://drc.ideablade.com/xwiki/bin/view/Documentation/SavingBusinessObjects#x_footnote_12 - 12 ."
Basically you will import the graph back to the main EM.
 
It seems when I call SaveChangesAsync on the second entity model it is not being committed to the database.
Are you checking the datasource after the SaveChangesAsync is completed? It won't show on the datasource until it completes.
 
1) The dependency graph is not picking up items which are still being loaded asynchronously
same as above. The asynchronous operation must be completed.
 
3) Doesn't like many to many relationships...
Based on the error message, it seems you are "crossing" entities between more than one entity manager. An entity can only belong to one entity manager. (when you import into a second entity manager, you actually have 2 copies of the same entity) Can you provide a test case reproducing this issue?
 
Below is a simple example (based on the example at http://drc.ideablade.com/xwiki/bin/view/Documentation/SavingBusinessObjects#HDependencyGraphRetrieval - http://drc.ideablade.com/xwiki/bin/view/Documentation/SavingBusinessObjects#HDependencyGraphRetrieval ) using multiple entity managers using async operations.
 
private void MainPage_Loaded(object sender, RoutedEventArgs e) {
  NorthwindIBEntities em1 = new NorthwindIBEntities();
  NorthwindIBEntities em2 = new NorthwindIBEntities();
  int employeeID = 1;
  var targetedEmployeesQuery = em1.Employees
    .Where(emp => emp.EmployeeID == employeeID)
    .Include("Orders.OrderDetails.Product");
 
  var queryAsync = em1.ExecuteQueryAsync(targetedEmployeesQuery);
 
  queryAsync.Completed += (q, queryArgs) => {
    List<Employee> employees = new List<Employee>(queryArgs.Results);
    Employee anEmployee = employees[0];
    // Create roots list and add the employee.
    List<Entity> roots = new List<Entity>();
    em2.ImportEntities(new Entity[] { anEmployee }, MergeStrategy.OverwriteChanges);
    //edit data on _em2
    var myEditableEmployee = em2.Employees.With(QueryStrategy.CacheOnly).First();
    myEditableEmployee.FirstName = ModifyString(myEditableEmployee.FirstName);
    var op2 = em2.SaveChangesAsync();
    op2.Completed += (s, savedArgs) => {
      em1.ImportEntities(savedArgs.Entities, MergeStrategy.OverwriteChanges);
      //checking if saved items successfully imported back to _em1
      var myEmployeeBackToEM1 = em1.Employees.With(QueryStrategy.CacheOnly).First();
    };
  };
}
 
private String ModifyString(String temp) {
  if (String.IsNullOrEmpty(temp)) {
    return "X";
  } else if (temp.EndsWith("X")) {
    return temp.Substring(0, temp.Length - 1);
  } else {
    return temp + "X";
  }
}
 


Posted By: cjohnson84
Date Posted: 06-Oct-2010 at 7:27am
I've been playing with the concepts demonstrated in the sample code above and while this code works well in the case of modified Employee entities or even newly added Employee entities, how do you handle the case where you have deleted an entity in em2?
 
In this case, the SaveChangesAsync call returns saveArgs.Entities containing a "Detached" entity.  When you import the detached entity into em1 with the following line:
 
em1.ImportEntities(savedArgs.Entities, MergeStrategy.OverwriteChanges);
 
Nothing happens...em1 is not "synced".  I was hoping the entity that was deleted in em2 would be removed from em1.
 
How do you handle this scenario or is my thinking wrong here?


Posted By: sbelini
Date Posted: 07-Oct-2010 at 10:57am
A Detached entity is not part of any entity manager therefore cannot be imported into another entity manager.
 
A way to handle this sitation is to keep track of the entities that have been deleted (i.e. save callback or SaveResult) on one entity manager and remove then from the other entity managers. ( .RemoveEntity or .RemoveEntities )


Posted By: cjohnson84
Date Posted: 07-Oct-2010 at 11:02am
Thank you Silvio for the feedback!  I'll give your suggestion a try.



Print Page | Close Window