2011-04-29 239 views
31

我将在具有外键的Employee和Team实体之间创建两个引用。 所以我定义了两个实体遵循实体框架4.1 InverseProperty属性和ForeignKey

public class Employee 
{ 
    public int EmployeeId { get; set; } 
    public string Name { get; set; } 

    [ForeignKey("FirstTeam")] 
    public int FirstTeamId { get; set; } 

    [InverseProperty("FirstEmployees")] 
    public virtual Team FirstTeam { get; set; } 

    [ForeignKey("SecondTeam")] 
    public int SecondTeamId { get; set; } 

    [InverseProperty("SecondEmployees")] 
    public virtual Team SecondTeam { get; set; } 
} 

public class Team 
{ 
    public int Id { get; set; } 
    public string TeamName { get; set; } 

    [InverseProperty("FirstTeam")] 
    public virtual ICollection<Employee> FirstEmployees { get; set; } 

    [InverseProperty("SecondTeam")] 
    public virtual ICollection<Employee> SecondEmployees { get; set; } 
} 

我认为这在理论上是正确的,但它显示了异常如下:

{"Introducing FOREIGN KEY constraint 'Employee_SecondTeam' on table 'Employees' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.\r\nCould not create constraint. See previous errors."} 

任何人可以帮助我吗?

在此先感谢 权

回答

54

这在理论上是正确的,但因为你的模型允许一个员工是第一和第二两个团队的成员,SQL服务器(未实体框架)不喜欢它。如果删除Team,则会导致到同一个Employee实体的多个删除路径。

如果您将外键定义为强制(不可为空),则不能与级联删除一起使用,级联删除在EF代码中默认使用。

如果你想避免异常,你必须使用流利的映射:

public Context : DbContext 
{ 
    public DbSet<Employee> Employees { get; set; } 
    public DbSet<Team> Teams { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     base.OnModelCreating(modelBuilder); 

     modelBuilder.Entity<Employee>() 
        .HasRequired(e => e.SecondTeam) 
        .WithMany(t => t.SecondEmployees) 
        .HasForeignKey(e => e.FirstTeamId) 
        .WillCascadeOnDelete(false); 

     ... 
    } 
} 

这将导致在场景中,你必须删除在删除前球队手动SecondTeam的成员。

+0

但是,如果你让EF生成密钥它会使它们可以为空(可选关系)。使用流利映射时,它也将使用列的名称作为外键。 – 2011-04-29 08:32:41

+0

谢谢拉迪斯拉夫。这正是我所期待的。 – Ray 2011-04-29 08:33:52

+0

抱歉删除我的评论。但是,如果是这样,我应该可以将外键属性定义为可以像public int那样为空吗? FirstTeamId {get;设置;}? – Ray 2011-04-29 09:36:22

2

全部是在以前的答案是正确的,但有一点是错误的,而不是SecondTeamId

modelBuilder.Entity<Employee>() 
       .HasRequired(e => e.SecondTeam) 
       .WithMany(t => t.SecondEmployees) 
       .HasForeignKey(e => e.SecondTeamId) // mistake 
       .WillCascadeOnDelete(false); 

FirstTeamId将导致在SecondTeam navigation财产将永远FirstTeam