.Net Entity Framework CodeFirst 中多次重复引用同一个外键问题

实际项目中,经常会遇到在一个表中多次引用同一个表的主键的情况。比如在部门表Department中,有正副两个主管:PrimaryManager ,SecondManager 。

//部门类定义  
public class Department  {  
    public int ID { get; set; }  
    public string Name { get; set; }  

    public int PrimaryManagerID { get; set; }  
    public virtual Manager PrimaryManager { get; set; }

    public int SecondManagerID { get; set; } 
    public virtual Manager SecondManager { get; set; } 
}  

//管理者类定义  
public class Manager {  
    public int ID { get; set; }  
    public string Name { get; set; }  

    public virtual ICollection<Department> PrimaryDepartments { get; set; }   

    public virtual ICollection<Department> SecondDepartments { get; set; }   
}  

这种情况下,通过CF模式创建数据库时一般会提示:

将 FOREIGN KEY 约束 ‘FK_dbo.Department_dbo.Manager_SecondManagerID’ 引入表 ‘Department’ 可能会导致循环或多重级联路径。请指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。

这是因为CF模式下,为这两个主键都设置了级联删除,而sql中多次引用同一个外键只能有一个设置为级联。`

解决方案

1 在DbContext类中重写OnModelCreating取消级联删除

protected override void OnModelCreating(DbModelBuilder modelBuilder) {  
    modelBuilder.Entity<Department>().HasRequired(m => m.PrimaryManager).WithMany(n => n.PrimaryDepartments).HasForeignKey(m => m.PrimaryManagerID).WillCascadeOnDelete(false);  
    modelBuilder.Entity<Department>().HasRequired(m => m.SecondManager).WithMany(n => n.SecondDepartments).HasForeignKey(m => m.SecondManagerID).WillCascadeOnDelete(false);  

    modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();  

    base.OnModelCreating(modelBuilder);  
}  

2 通过逆向属性InverseProperty建立关联

如果删除外键列的话:

//部门类定义  
public class Department  {  
    public int ID { get; set; }  
    public string Name { get; set; }  

    //public int PrimaryManagerID { get; set; }  
    public virtual Manager PrimaryManager { get; set; }

    //public int SecondManagerID { get; set; } 
    public virtual Manager SecondManager { get; set; } 
}  

生成的sql如下:

CREATE TABLE [dbo].[Department] --部门表  
(  
[ID] [int] NOT NULL IDENTITY(1, 1),  
[Name] [nvarchar] (max) COLLATE Chinese_PRC_CI_AS NULL,  
[Manager_ID] [int] NULL,  
[Manager_ID1] [int] NULL,  
[PrimaryManager_ID] [int] NULL,  
[SecondManager_ID] [int] NULL  
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]  
GO  
ALTER TABLE [dbo].[Department] ADD CONSTRAINT [PK_dbo.Department] PRIMARY KEY CLUSTERED  ([ID]) ON [PRIMARY]  
GO  
CREATE NONCLUSTERED INDEX [IX_Manager_ID] ON [dbo].[Department] ([Manager_ID]) ON [PRIMARY]  
GO  
CREATE NONCLUSTERED INDEX [IX_Manager_ID1] ON [dbo].[Department] ([Manager_ID1]) ON [PRIMARY]  
GO  
CREATE NONCLUSTERED INDEX [IX_PrimaryManager_ID] ON [dbo].[Department] ([PrimaryManager_ID]) ON [PRIMARY]  
GO  
CREATE NONCLUSTERED INDEX [IX_SecondManager_ID] ON [dbo].[Department] ([SecondManager_ID]) ON [PRIMARY]  
GO  
ALTER TABLE [dbo].[Department] ADD CONSTRAINT [FK_dbo.Department_dbo.Manager_Manager_ID] FOREIGN KEY ([Manager_ID]) REFERENCES [dbo].[Manager] ([ID])  
GO  
ALTER TABLE [dbo].[Department] ADD CONSTRAINT [FK_dbo.Department_dbo.Manager_Manager_ID1] FOREIGN KEY ([Manager_ID1]) REFERENCES [dbo].[Manager] ([ID])  
GO  
ALTER TABLE [dbo].[Department] ADD CONSTRAINT [FK_dbo.Department_dbo.Manager_PrimaryManager_ID] FOREIGN KEY ([PrimaryManager_ID]) REFERENCES [dbo].[Manager] ([ID])  
GO  
ALTER TABLE [dbo].[Department] ADD CONSTRAINT [FK_dbo.Department_dbo.Manager_SecondManager_ID] FOREIGN KEY ([SecondManager_ID]) REFERENCES [dbo].[Manager] ([ID])  
GO  

但由于Department没有显示定义外键,且包含多重外键,所以导致CodeFirst因无法明确关系,使表中包含了四个而不是两个外键,解决办法就是使用InverseProperty(逆向属性)特性,它存在于System.ComponentModel.DataAnnotations.Schema命名空间,InverseProperty既然可以用在Department类,也可以用在Manager类,或两边都用:

//部门类定义  
public class Department  {  
    public int ID { get; set; }  
    public string Name { get; set; }  

    [InverseProperty("PrimaryDepartments")]  
    public virtual Manager PrimaryManager { get; set; }

    [InverseProperty("SecondDepartments")] 
    public virtual Manager SecondManager { get; set; } 
}  

//管理者类定义  
public class Manager {  
    public int ID { get; set; }  
    public string Name { get; set; }  

    [InverseProperty("PrimaryManager")] 
    public virtual ICollection<Department> PrimaryDepartments { get; set; }   

    [InverseProperty("SecondManager")]  
    public virtual ICollection<Department> SecondDepartments { get; set; }   
}  

转载自:http://blog.csdn.net/x_craft/article/details/40347249

猜你喜欢

转载自blog.csdn.net/anjingshen/article/details/73522353
今日推荐