使用 one-to-many 关系和字符串的复合键重新实例化 EF 类

Reinstantiating EF classes with one-to-many relationship and compound key of strings

我有以下 EF Code First 类,它似乎在一定程度上起作用。我也有初始化代码,这些 tables 使用来自其他地方的数据来播种,这些数据很长,而且似乎(我希望)对我的问题无关紧要。或者至少当我手动播种时,我看到了同样的行为问题。

请注意,这些 table 使用字符串作为主键,而不是 ID。另请注意,SubCategory table 有一个复合主键,其中包括 parent table、Category 的主键 CategoryCode。这也许是守旧派,ISAMish,但这是我必须使用的,并且在其他方​​面是合乎逻辑的。

public class Category
{
  [Key]
  public string CategoryCode { get; set; }
  public string Description { get; set; }

  public List<SubCategory> Sub Categories { get; set; }

  public Category()
  {
    this.SubCategories = new List<SubCategory>();
  }
}

public class SubCategory
{
  [Key, Column(Order = 0)]
  public string CategoryCode { get; set; }
  [Key, Column(Order = 1)]
  public string SubCategoryCode { get; set; }
  public string Description { get; set; }
  public Category Category { get; set; }

  public SubCategory() { }
}

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
  // Configures the one-many relationship between Categories and 
  //   SubCategories, and established the Foreign Key in SubCategories
  modelBuilder.Entity<Category>()
    .HasMany<SubCategory>(c => c.SubCategories)
    .WithRequired(s => s.Category)
    .HasForeignKey<string>(s => s.CategoryCode);
}

此结构允许相同的 SubCategoryCode,例如 "CONTR" 多次用于不同的 CategoryCode,例如 "REHAB" 和 "MAINT"。数据示例如下所示:

Categories

CategoryCode    Description
==================  =========================
BANK    Costs of banking fees and expenses
FUND    Funding Loans/Pmnts
INSUR   Property Insurance
MAINT   Maintenance Expenses
REHAB   Rehabilitation & Renovation Expenses

SubCategories

CategoryCode    SubCategoryCode Description
==================  =====================   ===========
FUND    LOAN    Monies borrowed to Entity
FUND    PMNT    Monies paid back by Entity
INSUR   BUILD   Builders Risk policy, including liability
INSUR   LANDL   Landlord policy, including liability
INSUR   MISC    Miscellaneous/Other
MAINT   CONTR   Contractor invoices, (labor, Materials, fees)
MAINT   MATL    Materials & Tooling
REHAB   CONTR   Contractor invoices, (labor, Materials, fees)
REHAB   MATL    Materials & Tooling

请注意,我似乎需要指定一个默认构造函数来添加 List 成员的实例化,否则此 属性 在实例化的类别 类 中最终为 null。

另请注意,我希望两者 类 都包含对彼此的引用 - 即,Category 有一个 List 成员来保存其组成的 SubCategory 数据,而 SubCategory 有一个 Category 成员来保存对其的引用parent.

这是我最大的问题。如果我只执行以下命令,我会得到填充类别列表 类;但是,每个 objects' 子类别列表 objects 都是空的(不为空,但有 0 个项目)。现在,在我们指责默认构造函数在这里建立空列表之前,请注意,如果没有该代码,每个类别实例都包含对其子类别列表的空引用。

using (var db = new BusinessDBContext())
{
  var Categories = db.Categories.Where(c => c.CategoryCode == "FUND").ToList();
}

但是,如果我添加实例化子类别列表,类别列表中的类别现在将在其中填充子类别列表。在我实例化 SubCategories 之前,它们不存在。而且,这种情况发生在类别查询之前还是之后似乎并不重要。

using (var db = new BusinessDBContext())
{
  var Categories = db.Categories.Where(c => c.CategoryCode == "FUND").ToList();
  var SubCategories = db.SubCategories.Where(s => s.CategoryCode == "FUND").ToList();
}

我漏掉了什么,或者误解了什么?

为什么 SubCategories 为 null 或带有 0 个项目,因为您不包括它是预加载的关系。如果您想使用延迟加载,您可以在导航中使用 virtual 关键字 属性:

延迟加载:

public virtual List<SubCategory> SubCategories { get; set; }

预加载:

db.Categories.Where(c => c.CategoryCode == "FUND").Include(x => x.SubCategories ).ToList();

Read More.