实体框架代码与同一类的第一个双重关系

时间:2012-08-02 20:43:54

标签: c# asp.net .net entity-framework

我有一个与类似页面关联的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.

谢谢!

1 个答案:

答案 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与数据库,您将有一个从页面到关联的后向引用(您在此处尝试执行的操作),但在数据库本身的实际实体关系模型中没有。它们是虚拟参考。

修改

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

我会调查它。