我有一个与类似页面关联的Page
类。每个关联都有关于该关联的其他信息。这是已定义为Page
的表示的类。
public class Page {
[Key]
public virtual int Id { get; protected set; }
[Required]
[StringLength(32)]
public virtual string Name { get; set; }
[InverseProperty("Page")]
public virtual ICollection<Association> Associations { get; set; }
}
每个页面都可以与任意数量的其他页面相关联。这将被定义为源页面和目标页面。我不介意关联是单向还是双向,在我的特定情况下要么合理(我更喜欢双向关联,很难)。这是关联类..
public class Association {
[Key, Column(Order = 0)]
public virtual int PageId { get; protected set; } // SOURCE
[Required]
public virtual Page Page { get; set; } // SOURCE
[Key, Column(Order = 1)]
public virtual int TargetId { get; protected set; } // TARGET
[Required]
public virtual Page Target { get; set; } // TARGET
[Required]
[StringLength(32)]
public virtual string InformationAboutTheAssociation { get; set; }
}
现在我有以下背景......
public class DbCtx : DbContext {
public DbSet<Association> Associations { get; set; }
public DbSet<Page> Pages { get; set; }
}
问题是SQL Express抱怨可能的循环引用(事实并非如此,但它过于保护)。如何解决为接受描述的场景而生成的方案?
Introducing FOREIGN KEY constraint 'FK_dbo.Associations_dbo.Pages_TargetId' on table 'Associations' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
谢谢!
答案 0 :(得分:4)
<强> RESPONSE 强>
执行错误告诉您的操作。
指定ON DELETE NO ACTION或ON UPDATE NO ACTION 。由于你有两个外键到同一个实体,并且模型第一个(可能)默认插入on delete cascade
,你必须禁用它,因为当一个页面被删除时,该关联将尝试被第一个外键删除但由于第二个外键会失败。
修改3
public class DbCtx : DbContext {
public DbSet<Association> Associations { get; set; }
public DbSet<Page> Pages { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
modelBuilder.Entity<Association>()
.HasRequired(x => x.Page)
.WithMany(x => x.Associations)
.WillCascadeOnDelete(false);
}
}
我认为这应该有用。
删除网页实体
如果您尝试删除某个页面时没有on delete cascade
,那么如果您具有依赖于要删除的Page实体的关联实体,它将会失败。
因此,当您要删除页面时,必须先删除所有引用页面的关联。从Association到Page有一个外来约束(实际上有两个)。只使用其中一个并保持一致(Page或Target)。
由于您已经提出了这个问题,我只能得出结论,您并不真正了解SQL的工作方式,因此如果您还阅读了有关设计数据库和使用SQL的书籍,那就更好了。
我没有在EF中首先使用代码,但考虑到实体关系图,Page有“1对多”,关联和关联有两个“1对1”的页面。
这不是循环,因为它似乎是一个糟糕的设计。
规范化数据库。
如果你要设计数据库(数据库优先),你不需要页面和关联之间的“1对多”关系,因为你已经有了从“关联到”的关系“1对1”(其中两个)页。
因此,如果您想查找知道该pagId的特定关联,您可以拥有select * from association where pageId or targetId = the id you are looking for
。
如果您首先使用EF与数据库,您将有一个从页面到关联的后向引用(您在此处尝试执行的操作),但在数据库本身的实际实体关系模型中没有。它们是虚拟参考。
修改强>
我重读了这个问题,问题是从协会到页面的第二个引用。这很奇怪,因为数据库首先在这种情况下正常工作。
我会调查它。