c# - GraphDiff 中多对一和多对多关系中的空行插入

标签 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 调用拆分为多个调用?

提前致谢!

最佳答案

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

//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 复杂图(>2 深度)更新过程中出了点问题(或者至少我做了一些非常错误的事情)。

关于c# - GraphDiff 中多对一和多对多关系中的空行插入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27484465/

相关文章:

c# - 如何在 Entity Framework Code-First 中创建自定义 m2m 表

ef-code-first - EF Code First - 设置或影响外键引用名称

c# - c0000005 C 中的异常 :\Windows\Microsoft. NET\Framework\v4.0.30319\sos.threads 调试器扩展

c# - 返回 IQueryable 或 IEnumerable 会发生什么?

c# - 如何在 OData v4 API 中拥有动态可查询实体?

c# - 在 Entity Framework 中更新数据库

c# - 在生产环境中使用代码优先降级(回滚)数据库

c# - 如何在C#中的多个线程中一次处理信号

c# - SQLite 数据库插入错误约束

c# - MySql.Data.MySqlClient 引用在 Visual Studio 2015 中不起作用