Entity framework 实体框架核心变更跟踪器
请帮助我理解Entity Framework Core v2.2.2的奇怪行为 我有一个类Country,它包含区域集合,每个区域指的是它的所有者国家,也可以包含子区域集合,每个子区域指的是它的上级区域 请参见下面的UML图。 代码如下: 阶级国家Entity framework 实体框架核心变更跟踪器,entity-framework,entity-framework-core,change-tracking,Entity Framework,Entity Framework Core,Change Tracking,请帮助我理解Entity Framework Core v2.2.2的奇怪行为 我有一个类Country,它包含区域集合,每个区域指的是它的所有者国家,也可以包含子区域集合,每个子区域指的是它的上级区域 请参见下面的UML图。 代码如下: 阶级国家 public class Country { public Country(string name) { Name = name; Regions = new List<Region>()
public class Country
{
public Country(string name)
{
Name = name;
Regions = new List<Region>();
}
// for EF
protected Country()
{
}
public int Id { get; set; }
public string Name { get; set; }
public IList<Region> Regions { get; set; }
public Region CreateRegion(string name)
{
var region = new Region(name, this);
Regions.Add(region);
return region;
}
}
这是我得到的结构:
检查:
Console.WriteLine(country.Regions.Count); // 2
现在更有趣了。
我创建DbContext
public class CountryContext : DbContext
{
public CountryContext(DbContextOptions options) : base(options)
{
}
public DbSet<Country> Countries { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
}
}
这是我在图表上看到的:
实际上,问题是:如何使次区域不被添加到国家的区域集合中?您的问题是区域和次区域与国家的两种关系混淆了EF。 当您要求EF为您检索区域时,它所做的是搜索所有将其国家作为您导航的国家的区域,这意味着子区域也满足此标准
要解决此问题,您必须从
区域
中删除国家
属性。或者创建两个类Region
和subsection
,其中Region
具有Country
属性(如果层次结构不能深入到两个级别,则可能也没有SuperiorRegion
属性)。而且子区域
没有国家
属性。我完全同意,但我也假设有一种方法可以配置EF映射,但我还没有发现.EF在从DB加载顶级区域和子区域时需要一种方法来区分它们,并且它们都位于同一个表中。您还将国家与次区域关联,因此EF会认为这些区域也直接属于该国。您可以尝试为子区域保留Country null,但这种设计感觉不干净,很容易被忘记遵守此规则的其他代码破坏。从头开始设计,使您的模型不容易进入无效状态更好。
Console.WriteLine(country.Regions.Count); // 2
public class CountryContext : DbContext
{
public CountryContext(DbContextOptions options) : base(options)
{
}
public DbSet<Country> Countries { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
}
}
var options = new DbContextOptionsBuilder<CountryContext>()
.UseInMemoryDatabase(databaseName: "Countries")
.Options;
using (var db = new CountryContext(options))
{
db.Countries.Add(country);
}
Console.WriteLine(country.Regions.Count); //3!!!!!!!