Empty rows insertion in Many-to-One and Many-to-Many relationships in GraphDiff

c# ef-code-first entity-framework graphdiff

Question

I am utilizing the code-first methodology and the most recent version of Entity Framework combined with GraphDiff.

As I work to update aFood in this manner:

public void Update(Food food)
{
    using (var db = new DatabaseMappingContext())
    {
        food = db.UpdateGraph(food, map => map.OwnedEntity(f => f.FoodRecipe, withRecipe => withRecipe.
               OwnedCollection(r => r.RecipeSteps, withRecipeStep => withRecipeStep.
                   OwnedCollection(rs => rs.StartObjectSlots, withStartObjectSlots => withStartObjectSlots.
                       AssociatedEntity(sos => sos.BelongingRecipeStepAsStart)
                   ).
                   OwnedCollection(rs => rs.EndObjectSlots, withEndObjectSlots => withEndObjectSlots.
                       AssociatedEntity(eos => eos.BelongingRecipeStepAsEnd)
                   ).
                   AssociatedEntity(rs => rs.ActionOfUser)
               ).
               AssociatedCollection(r => r.InteractiveObjects)
            ).
            AssociatedCollection(f => f.FoodVarieties));
        //....
        db.SaveChanges();
    }
}

StartObjectSlots and EndObjectSlots are two lists that both contain unrelated information. TheInteractiveObjects consists of items of aInteractiveObject type, which serves as the foundational type for a variety of object types that can be added. Let's say one of those derived kindsIntObjDerived has the attribute of One to Many. Now, I'm attempting to update the following entity in the following manner:

ServerAdapter sa = new ServerAdapter();
//Loading a food from DB.
Food food = sa.LoadAllFoods().First();
RecipeStep rs = new RecipeStep();
rs.Name = "This is a test recipe step";
//Adding a User Action from the database.
rs.ActionOfUser = sa.LoadAllUserActions().First();
//....
//Add the step in the recipe
food.FoodRecipe.RecipeSteps.Add(rs);
//Update the food.
sa.Update(food);

A brand-new, empty ActionOfUser entity is now added to the database when the code is run. In addition, three additional recipes—one with no data, one with some data, and one that is intended to be saved—are added to the database. Both conditions are undesirable, and I'm looking for a way out. I tried a few different things, but I decided to stick with this. Any recommendations? (I know that this appears to be two queries, but I decided to combine them because the database issue may be significant.)

I downloaded and assembled.GraphDiff I looked into what was happening and saw that some objects were being created that were empty other than their Entity ID value. I assume that these side effects are a result of the fact that I literally added a new node (a new RecipeStep) to the object graph, even though I'm not sure if graphdiff really supports this.

REVISED (tl; dr version): I attempted to use aUpdateGraph GraphDiff of an object with a graph depth greater than 2 should be called using Entity Framework. According to my testing, GraphDiff appears to be performing double insertions in graphs with a depth larger than 2, which takes a long time, especially if a new node is added with subnodes imported from the database. Should I choose a different strategy, such as splitting theUpdateGraph call into a number of calls?

I appreciate it in advance.

1
4
12/23/2014 7:56:11 PM

Accepted Answer

My final solution was to split the update procedure into many steps as a workaround.UpdateGraph calls that have a graph depth of two or fewer and manually add any additional sub-nodes to the graph

//Update food in total graph depth <= 2.
db.UpdateGraph(food, map => map.AssociatedCollection(f => f.FoodVarieties));

//.... (Other UpdateGraph calls with graph depth <=2)

//Update recipe steps of recipe in total graph depth <= 2.
foreach (RecipeStep recipeStep in food.FoodRecipe.RecipeSteps)
{
    recipeStep.ActionOfUser = db.UserActions.FirstOrDefault(ua => ua.EntityID == recipeStep.ActionOfUser.EntityID);

    //If you have to do an inner node adding operation in the graph, do it manually.
    if (recipeStep.EntityID == 0)
    {
        recipeStep.BelongingRecipe = db.Recipes.FirstOrDefault(r => r.EntityID == food.FoodRecipe.EntityID);
        db.RecipeSteps.Add(recipeStep);
    }
    else
    {
        //Map slots & recipeSteps applied manually here.
        recipeStep.StartObjectSlots.ForEach(sos => sos.BelongingRecipeStepAsStart = recipeStep);
        recipeStep.EndObjectSlots.ForEach(eos => eos.BelongingRecipeStepAsEnd = recipeStep);

        db.UpdateGraph(recipeStep, map => map.OwnedCollection(rs => rs.InteractiveObjectInstancesLists, withIOILists => withIOILists.
                OwnedCollection(ioil => ioil.InteractiveObjectsInstances)
            ).
            OwnedCollection(rs => rs.StartObjectSlots, withStartObjectSlots => withStartObjectSlots.
                AssociatedEntity(sos => sos.BelongingRecipeStepAsStart)
            ).
            OwnedCollection(rs => rs.EndObjectSlots, withEndObjectSlots => withEndObjectSlots.
                AssociatedEntity(eos => eos.BelongingRecipeStepAsEnd)
            ).
            AssociatedEntity(rs => rs.ActionOfUser)
        );

    }
}

The object's graph update was also done considerably more quickly than it had in the past, I noticed. There could be signs of something is not right in these.GraphDiff complicated graph update process (>2 depth) (or at least I was doing something terribly wrong).

0
12/25/2014 12:27:52 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow