我已经在这件事上挣扎了一段时间,不太明白发生了什么。我有一个卡片实体,它包含两个侧面(通常是2个)-并且卡片和侧面都有一个舞台。我正在使用EF CodeFirst迁移,迁移失败,错误如下:
在表‘side’上引入外键约束‘fk_dbo.sids_dbo.Cards_CardID’可能会导致循环或多个级联路径。指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他外键约束。
这是我的卡片实体:
public class Card
{
public Card()
{
Sides = new Collection<Side>();
Stage = Stage.ONE;
}
[Key]
[Required]
public virtual int CardId { get; set; }
[Required]
public virtual Stage Stage { get; set; }
[Required]
[ForeignKey("CardId")]
public virtual ICollection<Side> Sides { get; set; }
}
以下是我的Side实体:
public class Side
{
public Side()
{
Stage = Stage.ONE;
}
[Key]
[Required]
public virtual int SideId { get; set; }
[Required]
public virtual Stage Stage { get; set; }
[Required]
public int CardId { get; set; }
[ForeignKey("CardId")]
public virtual Card Card { get; set; }
}
这是我的舞台实体:
public class Stage
{
// Zero
public static readonly Stage ONE = new Stage(new TimeSpan(0, 0, 0), "ONE");
// Ten seconds
public static readonly Stage TWO = new Stage(new TimeSpan(0, 0, 10), "TWO");
public static IEnumerable<Stage> Values
{
get
{
yield return ONE;
yield return TWO;
}
}
public int StageId { get; set; }
private readonly TimeSpan span;
public string Title { get; set; }
Stage(TimeSpan span, string title)
{
this.span = span;
this.Title = title;
}
public TimeSpan Span { get { return span; } }
}
奇怪的是,如果我在Stage类中添加以下内容:
public int? SideId { get; set; }
[ForeignKey("SideId")]
public virtual Side Side { get; set; }
迁移运行成功。如果我打开SSMS并查看表,我可以看到Stage_StageId
已添加到Cards
(如预期/所需),但Sides
不包含对Stage
的引用(非预期)。
如果我随后添加
[Required]
[ForeignKey("StageId")]
public virtual Stage Stage { get; set; }
public int StageId { get; set; }
在我的边类中,我看到StageId
列添加到我的Side
表中。
这是有效的,但是现在在我的整个应用程序中,任何对Stage
的引用都包含一个SideId
,这在某些情况下是完全不相关的。我只想给我的Card
和Side
实体一个基于上述Stage类的Stage
属性,如果可能的话,不会污染带有引用属性的Stage类...我做错了什么?
19条答案
按热度按时间qojgxg4l1#
在*.NET Core*中,我尝试了所有上面的答案--但没有任何成功。我在数据库结构中做了很多更改,每次都会添加新的迁移尝试
update-database
,但收到相同的错误。然后我开始逐个
remove-migration
,直到包管理器控制台抛出我异常:迁移‘20170827183131_*’已应用于数据库
之后,我添加了新的迁移(
add-migration
)和update-database
成功因此,我的建议是:清除所有临时迁移,直到您当前的数据库状态。
xfyts7mz2#
我遇到了同样的问题,并坚持了很长时间。以下步骤救了我一命。浏览约束并将onDelete*ReferentialAction从Cascade更改为NoAction
4jb9z9bj3#
你可以把这个添加到你的DataConext.cs中,这对我来说很有效……
plicqrtu4#
简单的方法是,编辑您的迁移文件
(cascadeDelete: true)
到(cascadeDelete: false)
,然后在您的包管理器控制台中分配更新数据库命令。如果上次迁移有问题,那么没关系。否则,检查您以前的迁移历史记录,复制这些内容,粘贴到您的最后一个迁移文件中,然后执行相同的操作。它非常适合我。c9x0cxw05#
前面提到的解决方案对我来说都不管用。我要做的是使用一个可为空的int(int?)在不需要的外键上(或者不是非空列键),然后删除我的一些迁移。
从删除迁移开始,然后尝试可以为空的int。
问题既是改装,也是模型设计。不需要更改代码。
epggiuax6#
在.NET 5<和.NET Core 2.0<中,您可以在
OnModelCreating
中使用.OnDelete(DeleteBehavior.Restrict)
Like@Nexus23 Answer,但不需要为每个模型禁用级联。联接实体类型配置多对多的示例:
资料来源:
Https://docs.microsoft.com/en-us/ef/core/modeling/relationships?tabs=fluent-api%2Cfluent-api-simple-key%2Csimple-key#join-entity-type-configuration
https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.deletebehavior?view=efcore-5.0
这确实需要您自己删除多对多关系,否则在删除父实体时会收到以下错误:
实体类型‘’和‘’之间的关联已被切断,但由于外键不可为Null,该关系被标记为Required或被隐式要求。如果在断开所需关系时应删除从属/子实体,请将该关系配置为使用级联删除。考虑使用‘DbContextOptionsBuilder.EnableSensitiveDataLogging’查看密钥值
您可以通过使用
DeleteBehavior.ClientCascade
来解决此问题,DeleteBehavior.ClientCascade
将允许EF在加载的实体上执行级联删除。https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.deletebehavior?view=efcore-5.0
kfgdxczn7#
现有的答案很好,我只是想补充说,我遇到这个错误是因为另一个原因。我想要在现有数据库上创建初始EF迁移,但我没有使用**-IgnoreChanges**标志,而是在空数据库上应用了更新数据库命令(也在现有的失败数据库上)。
相反,当当前的数据库结构是当前的数据库结构时,我必须运行以下命令:
数据库结构可能存在真正的问题,但要一步一个脚印地拯救世界……
t2a7ltrp8#
这听起来很奇怪,我不知道为什么,但在我的例子中,这是因为我的ConnectionString使用了“。在“数据源”属性中。一旦我将其更改为“本地主机”,它就像一个护身符一样工作。不需要其他改变。
oxf4rvwz9#
使您的外键属性可为空。这会奏效的。
mklgxw1f10#
当您的迁移失败时,您有两个选择:‘在表’RecommendedBook‘上引入外键约束’FK_dbo.RecommendedBook_dbo.Department_DepartmentID‘可能会导致循环或多个级联路径。指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他外键约束。无法创建约束或索引。请参阅前面的错误。‘
下面是一个使用‘Modify Other Foreign Key Constraints’的示例,方法是在迁移文件中将‘CascadeDelete’设置为FALSE,然后运行‘UPDATE-DATABASE’。
h7appiyu11#
只是为了文档目的,对于将来会出现的人来说,这个问题可以像这样简单地解决,使用这个方法,你可以做一次禁用的方法,你可以正常地访问你的方法
将此方法添加到上下文数据库类:
6uxekuva12#
我解决了这个问题。当您添加迁移时,在up()方法中将有如下一行:
如果您只需从末尾删除CascadeDelete,它就会起作用。
zzoitvuj13#
我也有这个问题,我立即用this answer from a similar thread解决了它
在我的例子中,我不想删除键删除时的从属记录。如果您的情况是这种情况,只需将迁移中的布尔值更改为False:
如果您正在创建抛出此编译器错误的关系,但确实希望维护级联删除,则可能是您的关系有问题。
egdjgwm814#
因为
Stage
是必需的,所以所有涉及Stage
的一对多关系在默认情况下都将启用级联删除。这意味着,如果您删除Stage
实体Side
Card
,由于Card
和Side
具有所需的一对多关系,并且默认情况下再次启用级联删除,因此它将从Card
级联到Side
因此,您有两条从
Stage
到Side
的级联删除路径,这会导致异常。您必须使
Stage
在至少一个实体中是可选的(即,从Stage
属性中删除[Required]
属性),或者使用Fluent API禁用级联删除(使用数据注解不可能):suzh9iv815#
在.NET Core中,我将onDelete选项更改为ReferencialAction.NoAction