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的子级别