4

我有一个Page要与类似页面关联的类。每个关联都有关于该关联的附加信息。这是已定义为 a 表示的类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.

谢谢!

4

1 回答 1

4

回复

做错误告诉你的事情。 指定 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 时,您必须首先删除引用该 Page 的所有关联。从关联到页面,您有一个外部约束(实际上是其中两个)。只使用其中一个并保持一致(页面或目标)。

既然你问了这个问题,我只能得出结论,你并不真正了解 SQL 是如何工作的,所以如果你还阅读一本关于设计数据库和使用 SQL 的书会更好。


我没有在 EF 中首先使用代码,但考虑到实体关系图,Page 与 Association 有“一对多”,Association 与 Page 有两个“1 to 1”。

这不是循环的吗,因为它看起来像是一个糟糕的设计。

规范化数据库。

如果您要设计数据库(首先是数据库),则不需要页面和关联之间的“一对多”关系,因为您已经拥有从关联到页面的“一对一”关系(其中两个)。因此,如果您想查找知道 pagId 的特定关联,您可以拥有一个select * from association where pageId or targetId = the id you are looking for.

如果您首先将 EF 与数据库一起使用,您将有一个从页面到关联的反向引用(您在此处尝试执行的操作),但不会在数据库本身的实际实体关系模型中。它们是虚拟参考。

编辑:

我重读了这个问题,问题是协会对页面的第二次引用。这很奇怪,因为数据库首先在这种情况下可以正常工作。

我会仔细看看的。

于 2012-08-02T21:06:47.523 回答