Entity Framework 4.1 InverseProperty 属性和ForeignKey

Posted

技术标签:

【中文标题】Entity Framework 4.1 InverseProperty 属性和ForeignKey【英文标题】:Entity Framework 4.1 InverseProperty Attribute and ForeignKey 【发布时间】:2011-08-15 06:20:17 【问题描述】:

我将使用外键在 Employee 和 Team 实体之间创建两个引用。 所以我定义了两个实体如下

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."

谁能帮帮我?

提前致谢 权

【问题讨论】:

【参考方案1】:

上一个答案都是正确的,但有一件事是错误的

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

FirstTeamId 而不是SecondTeamId 将导致SecondTeam navigation 中的属性将始终为FirstTeam

【讨论】:

【参考方案2】:

理论上是正确的,但 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 的成员。

【讨论】:

但是,如果您让 EF 生成密钥,它将使它们可以为空(可选关系)。使用流畅映射时,它还将使用列名作为外键。 谢谢拉迪斯拉夫。这正是我想要的。 抱歉删除了我的 cmets。但是,如果是这样,如果我将外键属性定义为像 public int 一样可以为空,是否有可能? FirstTeamId get;设置; ? @LadislavMrnka 是否有属性而不是 fluent? 我发现我必须使用 modelBuilder.Conventions.Remove();让类似的事情发挥作用

以上是关于Entity Framework 4.1 InverseProperty 属性和ForeignKey的主要内容,如果未能解决你的问题,请参考以下文章

Entity Framework 4.1 InverseProperty 属性和ForeignKey

Entity Framework 4.1 Fluent API 属性

卸载 Entity Framework 4.1 六月 CTP

通过 Entity Framework 4.1 中的用户定义函数进行热切加载

Entity Framework 4.1 - 映射错误的模式

Entity Framework 4.1 - 非键列之间的关系