如何使用 EF Code First Fluient API 从主表配置多个外键引用到同一个表

Posted

技术标签:

【中文标题】如何使用 EF Code First Fluient API 从主表配置多个外键引用到同一个表【英文标题】:How to configure multiple Foreignkey referancing to same table from main table using EF Code First Fluient API 【发布时间】:2011-07-12 05:59:41 【问题描述】:

我必须使用现有的桌面应用程序数据库设计一个 Web 应用程序。根据现有数据库,我有以下类

public class Company


    #region Primitive Properties

    public virtual int CompanyID  get; set; 
    public virtual string CompanyName  get; set; 

    public virtual bool IsCustomer  get; set; 
    public virtual string CustomerCode  get; set; 
    public virtual bool IsPotentialCustomer  get; set; 

    public virtual bool IsSupplier  get; set; 
    public virtual string SupplierCode  get; set; 
    public virtual bool IsPotentialSupplier  get; set; 

    public CompanyCategoryCodes CustomerCategoryCode  get; set; 
    public CompanyCategoryCodes SupplierCategoryCode  get; set; 
    public CountryCode CountryCode  get; set; 



public class CompanyCategoryCodes

    public virtual int CategoryID  get; set; 
    public virtual string CategoryCodes  get; set; 
    public virtual bool PotentialCustomer  get; set; 
    public virtual bool PotentialSupplier  get; set; 
    public virtual System.DateTime LastModifiedDate  get; set; 
    public virtual bool Manufacturer  get; set; 


public class CountryCode

    public virtual int CountryCodeID   get; set; 
    public virtual string Code  get; set; 
    public virtual string Description   get; set; 
    public virtual bool DefaultCode  get; set; 
    public virtual bool EECVATApplies  get; set; 
    public virtual System.DateTime LastModifiedDate  get; set; 
    public virtual bool FixedAddressFormat  get; set; 

EF 代码第一个默认框架是创建名为“CustomerCategoryCode_CategoryID”、“SupplierCategoryCode_CategoryID”、“CountryCode_CountryCodeID”的外键。我希望这个外键名称与我的旧数据库表一致,例如“客户类别代码 ID”、“供应商类别代码 ID”、“国家代码 ID”。我如何使用 EF Code First Fluient API 来做到这一点。我尝试使用 Fluient API 映射来执行此操作,但出现“SupplierCategoryCode_CategoryCodeID”错误,因为“CustomerCategoryCode_CategoryID”也位于同一张表“CompanyCategoryCode”。另外,如果有任何使用数据注释的选项,那么也请告诉我如何实现这一点。

【问题讨论】:

【参考方案1】:

您必须手动重新映射每个导航属性以定义其键。比如:

modelBuilder.Entity<Company>()
            .HasRequired(c => c.CountryCode)
            .WithMany()
            .HasForeignKey("CountryCodeID");

modelBuilder.Entity<Company>()
            .HasMany(c => c.CustomerCategoryCode)
            .WithOptional()
            .HasForeignKey("CustomerCategoryCodeID")
            .WillCascadeOnDelete(false);

modelBuilder.Entity<Company>()
            .HasMany(c => c.SupplierCategoryCode)
            .WithOptional()
            .HasForeignKey("SupplierCategoryCodeID")
            .WillCascadeOnDelete(false); 

除非您在每个依赖实体中定义导航属性和外键属性,否则无法使用数据注释:

public class Company

    ...

    [ForeignKey("CountryCode")]
    public virtual int CountryCodeID  get; set; 
    public CountryCode CountryCode  get; set; 

【讨论】:

错误消息是“在表 'Company' 上引入 FOREIGN KEY 约束 'CountryCode_Companies' 可能会导致循环或多个级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。无法创建约束。查看以前的错误。" 我们是否需要对 ON DELETE NO ACTION 或 ON UPDATE NO ACTION 做任何事情?仅当我尝试在一个表(公司)中有 2 个 ForiegnKeys(CustomerCategoryCodeID,SupplierCategoryCodeID)尝试引用同一个表(CompanyCategoryCode)时才会发生这种情况 是的,最后两个映射中的至少一个必须以 .WillCascadeOnDelete(false) 结尾,因为理论上 SupplierCategoryCodeIDCustomerCategoryCodeID 都可以指向导致多个级联路径的同一记录 - 这是不允许的SQL 服务器。 你说得对,我也尝试了同样的方法,现在工作正常,但我还需要添加 Public ICollection CustomerCompanies get;放; 和公共 ICollection SupplierCompanies get; set; 我的 CompanyCategoryCodes 类中的属性,否则它将不起作用。 CountryCode 类也是如此,所以现在我的类和映射类将如下所示并正常工作 我不能在这里放长类文件注释,所以我将在 8 小时后给出我所做的代码更改,因为系统将允许我在 8 小时后回答我自己的问题。感谢所有试图帮助我的人。【参考方案2】:

在你的上下文类中,你需要重写 OnModelCreating 并映射键,它应该看起来像这样:

protected override void OnModelCreating(DbModelBuilder modelBuilder)

             modelBuilder.Entity<Company>()
                .HasRequired(c => c.CustomerCategoryCode)
                .WithMany() 
                .Map(mc => mc.MapKey("CustomerCategoryCodeID"));

【讨论】:

它可能在 OnModelCreating 中工作,但我使用了单独的 Mapping 类,当我尝试将“CustomerCategoryCodeID”和“SupplieCategoryCodeID”指向同一张表“CompanyCategoryCode”时它给了我错误 错误是什么?除了 MapKey 之外,您是否将参数更新为 HasRequired?听起来您可能忘记在复制时将 c.CustomerCategoryCode 更新为 c.SupplierCategoryCode。只是猜测...... 错误消息是“在表 'Company' 上引入 FOREIGN KEY 约束 'CountryCode_Companies' 可能会导致循环或多个级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。无法创建约束。查看以前的错误。"

以上是关于如何使用 EF Code First Fluient API 从主表配置多个外键引用到同一个表的主要内容,如果未能解决你的问题,请参考以下文章

使用 EF4 Code First 时如何控制生成的 nvarchar 列的长度?

EF Code First - 如何设置标识增量

EF 7 Code First

如何使用EF Core Code-First桥接自己的表

如何使用 Code-First EF 4.1 从数据库中删除多个项目

EF Code-First如何使用复合键从表中读取A.