简体   繁体   中英

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

I am using GraphDiff, along with the latest version of the Entity Framework, following the code-first approach.

I am trying to update a Food entity this way:

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 2 lists containing some other, irrelevant data. The InteractiveObjects contains objects of a InteractiveObject type, which is the base type for a number of object types that can be put there. One of those derived types (let's say IntObjDerived has a One-to-Many property). Now, I am trying to update the following entity this way:

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);

Now, when the code is executed, a new empty ActionOfUser entity is inserted into the database. Additionally, a new empty entity is inserted for each of the one-to-many navigation properties of the entities mentioned above three new recipes are inserted in the database, one of empty data, one half filled and this one supposed to be saved. Both situations are unwanted, and I am trying to find the solution. I experimented with some changes, but I have stuck with this. Any suggestions? (I know that this seems to be 2 questions, but I thought to put it as one as it might be relevant-same problem in database).

EDIT: I downloaded and compiled GraphDiff in order to inspect what is going on, and I noticed the creation of some objects that are empty except from their Entity ID value. I guess that those side effects are caused because practically I add a new node to the object graph (a new RecipeStep) and I am not sure if graphdiff fully supports this.

UPDATE ( tl; dr version): I tried to apply a UpdateGraph call using Entity Framework's GraphDiff of an object with graph depth greater than 2. By what I have tried, it seems that GraphDiff is applying double insertions in graphs of depth greater than 2 and it takes a lots of time, especially if a new node is added with subnodes loaded from the database. Should I follow a different approach, for example split the UpdateGraph call into multiple calls?

Thank you in advance!

What I finally applied as a workaround, was to perform the update operation by splitting it into multiple UpdateGraph calls with graph depth less than or equal to 2 and apply manually any sub-node addition 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)
        );

    }
}

Also, I noticed that the object's graph update was completed much faster than before. These might be indications of something going wrong in GraphDiff complex graph (>2 depth) updating process (or at least I was doing something terribly wrong).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM