0

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

请注意,这些表使用字符串作为主键,而不是 ID。另请注意,SubCategory 表有一个复合主键,其中包括父表、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 成员的实例化,否则此属性在实例化的 Category 类中最终为 null。

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

在这里,我遇到了最大的问题。如果我只是执行以下操作,我会得到填充类别类的列表;但是,这些对象的 SubCategory 对象列表中的每一个都是空的(不为空,但有 0 个项目)。现在,在我们责怪此处建立空列表的默认构造函数之前,请注意,如果没有该代码,每个 Category 实例都包含对其 SubCategory List 的 Null 引用。

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();
}

我错过了什么,或者其他误解?

4

1 回答 1

0

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

延迟加载:

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

急切加载:

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

阅读更多

于 2018-03-27T16:36:28.117 回答