2012-08-02 82 views
4

我有一个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

哪个EF? 4.3,5.0? – 2012-08-02 21:21:13

+0

要么。我现在使用5.0,但也可以使用4.3。 – 2012-08-02 21:42:22

+0

使用5.0。它在速度部门有所改进。 – amb 2012-08-02 22:01:42

回答

4

响应

做什么错误告诉你。 指定ON DELETE NO ACTION或ON UPDATE NO ACTION。既然你有两个外键给同一个实体,并且默认on delete cascade为默认的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在协会做,如果你试图删除页面,如果你有这取决于你想要删除的页面实体协会实体就会失败。

所以,当你想删除一个页面,你必须首先删除所有的关联,引用页面。你有一个外部约束(其中两个实际上)从Association到Page。只使用其中的一个并保持一致(页面或目标)。

既然你问了这个问题,我只能断定你并不知道SQL是如何工作的,所以如果你还读了一本关于设计数据库和使用SQL的书,那会更好。


我没有第一次使用的代码EF但考虑到实体关系图,页面有“1对多”公司章程和协会有两个“1对1”的页面。

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

规范化数据库。

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

,如果您第一次使用EF与数据库,你就必须从页面关联一个反向引用(你正在尝试做的),但不是在数据库本身的实际实体关系模型。它们是虚拟参考。

编辑:

我重读的问题,问题是该协会第二参考页。这很奇怪,因为数据库首先在这种情况下正常工作。

我会考虑它。

+1

准确地说,如何在没有实体引用自身的情况下对树层次结构的关系模型(或者在这种情况下是有向图)进行规范化?任何“一对多”关系实际上只是您提出的改变所具有的“一对一”或“多对一”关系的逆转。使用ORM的主要优点之一是它们可以直观地导航并在模型类中显式捕获,而不必处理“虚拟引用”。 – millimoose 2012-08-02 21:08:54

+0

你必须对树层次更具体。父实体不需要具有对子实体的引用(只有子实体具有父实体的外键)。你可以让实体引用自己(因为设计),并不意味着它是循环的,但在这种情况下,循环警告看起来是正确的,因为你实体之间互相引用。 – amb 2012-08-02 21:15:15

+0

即使我使用ORM(并且我使用它很多),我仍然倾向于手动设计我的数据库,然后首先使用EF数据库。来回引用会自动添加,实际上是因为它们不驻留在数据库方案中。在引擎盖下,后退引用仅仅是一个'你不写的通过主键选择'。 – amb 2012-08-02 21:16:32

相关问题