Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从单个路径删除时删除级联_C#_Asp.net_Asp.net Mvc_Entity Framework_Entity Framework 6 - Fatal编程技术网

C# 从单个路径删除时删除级联

C# 从单个路径删除时删除级联,c#,asp.net,asp.net-mvc,entity-framework,entity-framework-6,C#,Asp.net,Asp.net Mvc,Entity Framework,Entity Framework 6,遵循我的数据模型。我去掉了所有不重要的注释,以保持简洁 public class Bubble { public int Id { get; set; } public string Name { get; set; } public ICollection<Level> Levels { get; set; } } public class Level { public int Id { get; set; } public int Bub

遵循我的数据模型。我去掉了所有不重要的注释,以保持简洁

public class Bubble
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<Level> Levels { get; set; }
}

public class Level
{
    public int Id { get; set; }
    public int BubbleId { get; set; }
    [ForeignKey("ParentLevel")]
    public int? LevelId { get; set; }

    public string Name { get; set; }

    public Level ParentLevel { get; set; }
    public Bubble Bubble { get; set; }

    public ICollection<Level> Levels { get; set; }
    public ICollection<Item> Items { get; set; }
}

public class Item
{
    public int Id { get; set; }
    public int LevelId { get; set; }

    public string Name { get; set; }

    public Level Level { get; set; }
}

在层叠关闭时无法删除气泡的原因是,对于要删除的气泡,仍然有带有外键的级别

此外,假设要删除气泡2。气泡2的顶层为20。
气泡3有一个级别21,它是级别20的子级别。
气泡4有一个标高22,它是标高21的子标高

如果删除气泡2,是否应删除气泡3和4的级别

让我们假设您的软件没有这些特性:没有循环级别引用,并且所有级别都来自同一个气泡

在删除标高和编号之前,可以将要删除的编号的所有标高的所有标高ID都置零:

// we want to remove Bubble 2
var levelsToRemove = dbContext.Levels.Where(level => level.BubbleId == 2).ToList();
// nullify all levelIds:
foreach (var levelToRemove in levelsToRemove)
{
    levelToRemove.LevelId = null;
}
// TODO: maybe we need an extra SaveChanges

// Remove the Levels and the Bubble:
dbContext.Levels.RemoveRange(levelsToRemove);

var bubbleToRemove = dbContext.Find(2); // TODO: exception if not found
dbContext.Bubbles.Remove(bubbleToRemove);
dbContext.SaveChanges();
适当的解决办法 事实上,您的代码必须防止循环引用和级别为其他气泡级别的子级别的气泡,这应该让您知道您的数据库不够规范化

考虑给你的收藏品。这将是一对零或一个关系,或者如果所有级别的气泡2都有几个共同点,考虑把这些东西放到一个水平集合中,让你的气泡有零或更多的水平集合(一对多)。 每个LevelCollection只属于一个气泡。LevelCollection具有零个或多个级别

现在可以保证,如果LevelCollection 42属于气泡2,则LevelCollection 42的所有级别都属于气泡2。可以从级别中删除外键BubbleId

这不会阻止循环级别引用,但会阻止一棵树中的级别属于不同的气泡

为什么必须关闭级联 通常,如果你有一对多的关系,比如一所学校和他的许多学生,当你删除一所学校时,你也要自动删除它的所有学生。当“层叠”处于启用状态时,实体框架将首先删除所有具有您请求移动的项的外键的项,然后再删除您的项

这不能通过气泡和水平自动完成

让我们添加一些气泡和级别

                            Id | Name
Add Bubble with name A  =>  1  |  A

                                                  Id | BubbleId | LevelId
Add Level without Parent for Bubble 1         =>  10 |    1     |  null
Add sub Level of Level 10 Parent for Bubble 2 =>  11 |    1     |   10

Now give Level 10 a new LevelId               =>  10 |    1     |   11
好的,级联打开了,让我们移除气泡1

在实体框架能够做到这一点之前,它必须删除所有具有Bubble 1外键的内容。 所以我们需要先移除10级,我们不能,因为我们必须先移除11级。然而,11级不能被移除,因为10级不能被移除,等等

我们已经画了一个小圆圈,但是你可以想象如果你有一个1000层的圆圈会发生什么

您的代码可能会阻止您创建一个圆,但实体框架不能阻止您这样做


另一个问题:假设气泡2的级别为20。级别20是级别21的子级别,级别21具有气泡1的外键。如果删除气泡1,气泡2的级别会发生什么变化?有些人可能会说:它成为泡泡2的顶级,其他人可能会说:不,泡泡2失去了它的级别。实体框架无法检测到您想要的内容,因此您必须自己执行此操作并关闭层叠功能。

层叠功能关闭时无法删除气泡的原因是,您仍然有要删除的气泡的外键级别

此外,假设要删除气泡2。气泡2的顶层为20。
气泡3有一个级别21,它是级别20的子级别。
气泡4有一个标高22,它是标高21的子标高

如果删除气泡2,是否应删除气泡3和4的级别

让我们假设您的软件没有这些特性:没有循环级别引用,并且所有级别都来自同一个气泡

在删除标高和编号之前,可以将要删除的编号的所有标高的所有标高ID都置零:

// we want to remove Bubble 2
var levelsToRemove = dbContext.Levels.Where(level => level.BubbleId == 2).ToList();
// nullify all levelIds:
foreach (var levelToRemove in levelsToRemove)
{
    levelToRemove.LevelId = null;
}
// TODO: maybe we need an extra SaveChanges

// Remove the Levels and the Bubble:
dbContext.Levels.RemoveRange(levelsToRemove);

var bubbleToRemove = dbContext.Find(2); // TODO: exception if not found
dbContext.Bubbles.Remove(bubbleToRemove);
dbContext.SaveChanges();
适当的解决办法 事实上,您的代码必须防止循环引用和级别为其他气泡级别的子级别的气泡,这应该让您知道您的数据库不够规范化

考虑给你的收藏品。这将是一对零或一个关系,或者如果所有级别的气泡2都有几个共同点,考虑把这些东西放到一个水平集合中,让你的气泡有零或更多的水平集合(一对多)。 每个LevelCollection只属于一个气泡。LevelCollection具有零个或多个级别

现在可以保证,如果LevelCollection 42属于气泡2,则LevelCollection 42的所有级别都属于气泡2。可以从级别中删除外键BubbleId

这不会阻止循环级别引用,但会阻止一棵树中的级别属于不同的气泡

为什么必须关闭级联 通常,如果你有一对多的关系,比如一所学校和他的许多学生,当你删除一所学校时,你也要自动删除它的所有学生。当“层叠”处于启用状态时,实体框架将首先删除所有具有您请求移动的项的外键的项,然后再删除您的项

这不能通过气泡和水平自动完成

让我们添加一些气泡和级别

                            Id | Name
Add Bubble with name A  =>  1  |  A

                                                  Id | BubbleId | LevelId
Add Level without Parent for Bubble 1         =>  10 |    1     |  null
Add sub Level of Level 10 Parent for Bubble 2 =>  11 |    1     |   10

Now give Level 10 a new LevelId               =>  10 |    1     |   11
好的,级联打开了,让我们移除气泡1

在实体框架能够做到这一点之前,它必须删除所有具有Bubble 1外键的内容。 所以我们需要先移除10级,我们不能,因为我们必须先移除11级。然而,11级不能被移除,因为10级不能被移除,等等

我们已经画了一个小圆圈,但是你可以想象如果你有一个1000层的圆圈会发生什么

您的代码可能会阻止您创建一个圆,但实体框架不能阻止您这样做

另一个问题:假设气泡2的级别为20。级别20是级别21和级别21的子级别