I have the following EF Code First classes, which appear to be working to a point. I also have Initialization code that seeds these tables with data from elsewhere that is lengthy, and seems (I hope) inconsequential to my question. Or at the least when I seed manually I see the same behavior problem.
Note, that these tables use strings as their primary keys, and not ID's. Also note that the SubCategory table has a compound primary key that includes the parent table, Category's primary key, CategoryCode. This is, perhaps, old school, ISAMish, but it is what I have to work with, and is otherwise logical.
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);
}
This structure allows the same SubCategoryCode, say "CONTR" to be used more than once for different CategoryCodes, such as "REHAB" and "MAINT". A sample of data looks like this:
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
Note that I seemed to need to specify a default constructor to add instantiation of the List member, or this property ends up being null in instantiated Category classes.
Also note that I wish to have both classes include references to each other - i.e., Category has a List member to hold its constituent SubCategory data, and SubCategory has a Category member to hold a reference to its parent.
It is here that I have the greatest issue. If I just execute the following, I get List of populated Category classes; however, each of those objects' List of SubCategory objects is empty (not null, but there with 0 items). Now, before we blame the default constructor establishing the empty List here, note that without that code each of the Category instances contain a Null reference to their SubCategory List.
using (var db = new BusinessDBContext())
{
var Categories = db.Categories.Where(c => c.CategoryCode == "FUND").ToList();
}
But, if I add instantiating a List of SubCategory, the Category's in the List of Category will now have populated lists of SubCategory's within. They aren't there until I instantiate the SubCategories. And, it doesn't seem to matter if that happens before or after the query for Categories.
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();
}
What am I missing, or otherwise misunderstanding?
Why SubCategories
is null or with 0 item because you don't include this relation that it is Eager loading. if you want to use lazy loading you can use virtual
keyword in your navigation property:
Lazy Loading:
public virtual List<SubCategory> SubCategories { get; set; }
Eager Loading:
db.Categories.Where(c => c.CategoryCode == "FUND").Include(x => x.SubCategories ).ToList();
来源:https://stackoverflow.com/questions/49516733/reinstantiating-ef-classes-with-one-to-many-relationship-and-compound-key-of-str