次の EF Code First クラスがあり、ある程度機能しているようです。また、これらのテーブルに長い他の場所からのデータをシードする初期化コードもあり、私の質問には重要ではないようです (願っています)。または、少なくとも手動でシードすると、同じ動作の問題が発生します。
これらのテーブルは、ID ではなく文字列を主キーとして使用することに注意してください。また、SubCategory テーブルには、親テーブルである Category の主キーである CategoryCode を含む複合主キーがあることに注意してください。これはおそらく昔ながらの ISAM 風ですが、私が取り組まなければならないものであり、そうでなければ論理的です。
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);
}
この構造により、「CONTR」などの同じ SubCategoryCode を、「REHAB」や「MAINT」などの異なる CategoryCode に対して複数回使用できます。データのサンプルは次のようになります。
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 には、その構成要素である SubCategory データを保持するための List メンバーがあり、SubCategory には、その親への参照を保持するための Category メンバーがあります。
ここで私は最大の問題を抱えています。以下を実行すると、入力されたカテゴリ クラスのリストが取得されます。ただし、これらの各オブジェクトの SubCategory オブジェクトのリストは空です (null ではありませんが、アイテムはありません)。ここで、デフォルトのコンストラクターが空の List を確立していると非難する前に、そのコードがないと、Category インスタンスのそれぞれに SubCategory List への Null 参照が含まれていることに注意してください。
using (var db = new BusinessDBContext())
{
var Categories = db.Categories.Where(c => c.CategoryCode == "FUND").ToList();
}
しかし、SubCategory のリストのインスタンス化を追加すると、Category のリスト内のカテゴリに SubCategory のリストが取り込まれます。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();
}
私は何を見逃していますか、それとも誤解していますか?