SB2*_*055 275 .net entity-framework entity-framework-4 ef-code-first
我已经和它搏斗了一段时间,并且无法弄清楚发生了什么.我有一个卡片实体,其中包含Sides(通常为2个) - 卡片和侧面都有一个舞台.我正在使用EF Codefirst迁移,并且迁移失败并出现此错误:
在表'Sides'上引入FOREIGN KEY约束'FK_dbo.Sides_dbo.Cards_CardId'可能会导致循环或多个级联路径.指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他FOREIGN KEY约束.
这是我的卡片实体:
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; }
}
Run Code Online (Sandbox Code Playgroud)
这是我的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; }
}
Run Code Online (Sandbox Code Playgroud)
这是我的舞台实体:
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; } }
}
Run Code Online (Sandbox Code Playgroud)
奇怪的是,如果我将以下内容添加到Stage类中:
public int? SideId { get; set; }
[ForeignKey("SideId")]
public virtual Side Side { get; set; }
Run Code Online (Sandbox Code Playgroud)
迁移成功运行.如果我打开SSMS并查看表格,我可以看到Stage_StageId
已经添加到Cards
(如预期/期望的那样),但是不Sides
包含对Stage
(不是预期的)的引用.
如果我再添加
[Required]
[ForeignKey("StageId")]
public virtual Stage Stage { get; set; }
public int StageId { get; set; }
Run Code Online (Sandbox Code Playgroud)
对于我的Side类,我看到StageId
列已添加到我的Side
表中.
这是有效的,但现在在我的应用程序中,任何对Stage
包含a的引用SideId
,在某些情况下完全无关紧要. 我想基于上面的Stage类给我Card
和Side
实体一个Stage
属性,如果可能的话,不用参考属性污染舞台类 ......我做错了什么?
Sla*_*uma 354
因为Stage
是必需的,Stage
所涉及的所有一对多关系将默认启用级联删除.这意味着,如果您删除一个Stage
实体
Side
Card
,因为Card
并且Side
具有所需的一对多关系,默认情况下启用了级联删除,然后它将级联Card
到Side
所以,你必须从两个级联删除路径Stage
来Side
-这将导致异常.
您必须Stage
在至少一个实体中创建可选项(即[Required]
从Stage
属性中删除属性)或禁用使用Fluent API的级联删除(不能使用数据注释):
modelBuilder.Entity<Card>()
.HasRequired(c => c.Stage)
.WithMany()
.WillCascadeOnDelete(false);
modelBuilder.Entity<Side>()
.HasRequired(s => s.Stage)
.WithMany()
.WillCascadeOnDelete(false);
Run Code Online (Sandbox Code Playgroud)
Cem*_*tlu 52
我有一张与其他人有圆形关系的桌子,我也遇到了同样的错误.原来它是关于不可空的外键.如果key不可为空,则必须删除相关对象,并且循环关系不允许这样做.所以使用可以为空的外键.
[ForeignKey("StageId")]
public virtual Stage Stage { get; set; }
public int? StageId { get; set; }
Run Code Online (Sandbox Code Playgroud)
Nex*_*s23 31
有人想知道如何在EF核心中做到这一点:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
foreach (var relationship in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()))
{
relationship.DeleteBehavior = DeleteBehavior.Restrict;
}
..... rest of the code.....
Run Code Online (Sandbox Code Playgroud)
Sea*_*ean 21
当我从EF7模型迁移到EF6版本时,我收到了很多实体的错误.我不想一次一个地浏览每个实体,所以我使用了:
builder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
builder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
Run Code Online (Sandbox Code Playgroud)
Mus*_*yed 17
您可以将cascadeDelete设置为false或true(在您的迁移Up()方法中).取决于您的要求.
AddForeignKey("dbo.Stories", "StatusId", "dbo.Status", "StatusID", cascadeDelete: false);
Run Code Online (Sandbox Code Playgroud)
在.NET Core中,我尝试了所有上面的答案 - 但没有成功。我在数据库结构中进行了很多更改,并且每次都尝试添加新的迁移update-database
,但收到了相同的错误。
remove-migration
然后我开始一一进行,直到程序包管理器控制台向我抛出异常:
迁移'20170827183131_***'已经应用到数据库
之后,我添加了新的迁移(add-migration
)并update-database
成功
所以我的建议是:清除所有临时迁移,直到当前的数据库状态。
我修好了.添加迁移时,在Up()方法中会有如下所示的行:
.ForeignKey("dbo.Members", t => t.MemberId, cascadeDelete:True)
Run Code Online (Sandbox Code Playgroud)
如果你只是从最后删除cascadeDelete它将工作.
只是为了文档的目的,对于未来的人来说,这件事可以像这样简单地解决,用这个方法,你可以做一个禁用一次的方法,你可以正常访问你的方法
将此方法添加到上下文数据库类:
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
}
Run Code Online (Sandbox Code Playgroud)
我也有这个问题,我通过类似线程的答案立即解决了它
就我而言,我不想删除密钥删除的依赖记录.如果在您的情况下就是这种情况,只需将迁移中的布尔值更改为false:
AddForeignKey("dbo.Stories", "StatusId", "dbo.Status", "StatusID", cascadeDelete: false);
Run Code Online (Sandbox Code Playgroud)
如果你正在创建抛出这个编译器错误但是想要保持级联删除的关系,那么很有可能; 你的人际关系有问题.
小智 5
在.NET Core中,我将onDelete选项更改为ReferencialAction.NoAction
constraints: table =>
{
table.PrimaryKey("PK_Schedule", x => x.Id);
table.ForeignKey(
name: "FK_Schedule_Teams_HomeId",
column: x => x.HomeId,
principalTable: "Teams",
principalColumn: "Id",
onDelete: ReferentialAction.NoAction);
table.ForeignKey(
name: "FK_Schedule_Teams_VisitorId",
column: x => x.VisitorId,
principalTable: "Teams",
principalColumn: "Id",
onDelete: ReferentialAction.NoAction);
});
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
192996 次 |
最近记录: |