在GraphDiff中的多对一和多对多关系中的空行插入

时间:2014-12-15 12:46:56

标签: c# entity-framework ef-code-first graphdiff

我正在使用GraphDiff以及最新版本的Entity Framework,遵循代码优先的方法。

我正在尝试以这种方式更新Food实体:

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

StartObjectSlotsEndObjectSlots是包含一些其他无关数据的2个列表。 InteractiveObjects包含InteractiveObject类型的对象,这是可以放在那里的许多对象类型的基本类型。其中一种派生类型(让我们说IntObjDerived具有一对多属性)。 现在,我试图以这种方式更新以下实体:

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

现在,当执行代码时,会将新的空ActionOfUser实体插入到数据库中。另外,为上面提到的实体的每个一对多导航属性插入一个新的空实体在数据库中插入三个新配方,一个空数据,一半填充,这个一个人应该得救。这两种情况都是不受欢迎的,我试图找到解决方案。我尝试了一些改变,但我坚持这一点。有什么建议? (我知道这似乎是2个问题,但我想把它作为一个,因为它可能是相关的 - 数据库中的相同问题)。

编辑:我下载并编译了GraphDiff以检查发生了什么,我注意到除了实体ID值之外,还创建了一些空的对象。 我猜这些副作用是因为实际上我添加一个新节点到对象图(一个新的RecipeStep),我不确定graphdiff是否完全支持这个。

更新(tl; dr版本):我尝试使用图片深度大于2的对象的Entity Framework&GraphDiff应用UpdateGraph调用。 根据我的尝试,似乎GraphDiff在深度大于2的图形中应用双重插入并且需要花费大量时间,特别是如果添加了从数据库加载的子节点的新节点。我应该采用不同的方法,例如将UpdateGraph电话分成多个电话吗?

提前谢谢!

1 个答案:

答案 0 :(得分:0)

我最终应用的解决方法是将更新操作拆分为多个UpdateGraph调用,图形深度小于或等于2,并手动应用任何子节点添加到图中:< / p>

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

    }
}

另外,我注意到对象的图形更新比以前更快完成。这些可能是GraphDiff复杂图形(&gt; 2深度)更新过程中出现问题的迹象(至少我做的事情非常糟糕)。