Entity Framework 核心:SQLite 的所有其他结果都缺少相关数据
Entity Framework Core: related data missing for every other result with SQLite
我在从数据库中检索数据时遇到了一个奇怪的问题。这是一个从 .NET Core 1.0 升级到 .NET Core 2.1 的项目。之前一切正常,但升级在加载相关数据时有一些奇怪的副作用。使用的确切版本是 2.1 for .NETCore.app; 2.1.4 用于 AspNetCore,2.1.4 用于 EntityFrameworkCore(.Sqlite)。
问题可以用以下模型来表达。插入后,首先添加一个 Match
,但没有相关的 Result
实体。然后,创建每个 Result
,最后用这些实例再次更新 Match
。这就是 Match
.
中可空 ID 字段的原因
public class Result
{
public int Id { get; set; }
public int MatchId { get; set; }
public Match Match { get; set; }
}
public class Match
{
public int Id { get; set; }
public int? HomeId { get; set; }
public int? AwayId { get; set; }
public Result Home { get; set; }
public Result Away { get; set; }
}
当我检索数据(例如,context.Results.Include(r => r.Match)
)并检查结果时,每个 other 结果都遗漏了相关数据。这似乎只发生在这些表上,所以我的猜测是由于模型的双向性而误入歧途。
检查员显示如下结果。应该注意的是,两个连续结果的集合总是指向相同的 Match
.
results
- [0]
Id = 1000
Match = Null
- [1]
Id = 1001
Match = <Match object>
- [2]
Id = 1002
Match = Null
- [3]
Id = 1003
Match = <Match object>
等等。我也无法将数据插入到这些表中(弹出类似问题),但此时让我们将其排除在这个问题的范围之外。
回答我自己的问题:问题出在关系映射中。有 several related questions 恰好与我的相匹配,但建议通常在于创建额外的字段以更好地描述映射。由于不会更改数据库模式,因此这不是一个选项。
附带说明一下,这个问题与 SQLite 没有太大关系。然而奇怪的是,事情曾经按照问题中的描述工作。我没有调查是什么原因造成的,但看起来 Entity Framework 的 SQLite 二进制文件处理这种情况的方式不同。并不是说这是一个错误,但作为版本之间的主要区别,它可能至少与此有关。
也就是说,解决方案。 ModelBuilder
最初有以下定义:
modelBuilder.Entity<Match>()
.HasOne(m => m.Home)
.WithMany()
.HasForeignKey(m => m.HomeId);
modelBuilder.Entity<Match>()
.HasOne(m => m.Away)
.WithMany()
.HasForeignKey(m => m.AwayId);
modelBuilder.Entity<Result>()
.HasOne(r => r.Match)
.WithOne()
.HasForeignKey<Result>(r => r.MatchId);
其中一个问题是来自 Match
的 WithMany
映射不正确。将其更改为 WithOne
- 尽管更正确 - 对问题没有任何影响。它已通过删除从 Result
到 Match
的关系映射得到修复。显然,这默默地映射了反向关系,选择两个关系之一朝向 Result
。因为(我假设)Entity Framework 会在指定一端后处理反向关系,所以可以(应该)将其排除以修复问题并保留所有导航。
为了完整性,最后的ModelBuilder
定义:
modelBuilder.Entity<Match>()
.HasOne(m => m.Home)
.WithOne()
.HasForeignKey(m => m.HomeId);
modelBuilder.Entity<Match>()
.HasOne(m => m.Away)
.WithOne()
.HasForeignKey(m => m.AwayId);
我在从数据库中检索数据时遇到了一个奇怪的问题。这是一个从 .NET Core 1.0 升级到 .NET Core 2.1 的项目。之前一切正常,但升级在加载相关数据时有一些奇怪的副作用。使用的确切版本是 2.1 for .NETCore.app; 2.1.4 用于 AspNetCore,2.1.4 用于 EntityFrameworkCore(.Sqlite)。
问题可以用以下模型来表达。插入后,首先添加一个 Match
,但没有相关的 Result
实体。然后,创建每个 Result
,最后用这些实例再次更新 Match
。这就是 Match
.
public class Result
{
public int Id { get; set; }
public int MatchId { get; set; }
public Match Match { get; set; }
}
public class Match
{
public int Id { get; set; }
public int? HomeId { get; set; }
public int? AwayId { get; set; }
public Result Home { get; set; }
public Result Away { get; set; }
}
当我检索数据(例如,context.Results.Include(r => r.Match)
)并检查结果时,每个 other 结果都遗漏了相关数据。这似乎只发生在这些表上,所以我的猜测是由于模型的双向性而误入歧途。
检查员显示如下结果。应该注意的是,两个连续结果的集合总是指向相同的 Match
.
results
- [0]
Id = 1000
Match = Null
- [1]
Id = 1001
Match = <Match object>
- [2]
Id = 1002
Match = Null
- [3]
Id = 1003
Match = <Match object>
等等。我也无法将数据插入到这些表中(弹出类似问题),但此时让我们将其排除在这个问题的范围之外。
回答我自己的问题:问题出在关系映射中。有 several related questions 恰好与我的相匹配,但建议通常在于创建额外的字段以更好地描述映射。由于不会更改数据库模式,因此这不是一个选项。
附带说明一下,这个问题与 SQLite 没有太大关系。然而奇怪的是,事情曾经按照问题中的描述工作。我没有调查是什么原因造成的,但看起来 Entity Framework 的 SQLite 二进制文件处理这种情况的方式不同。并不是说这是一个错误,但作为版本之间的主要区别,它可能至少与此有关。
也就是说,解决方案。 ModelBuilder
最初有以下定义:
modelBuilder.Entity<Match>()
.HasOne(m => m.Home)
.WithMany()
.HasForeignKey(m => m.HomeId);
modelBuilder.Entity<Match>()
.HasOne(m => m.Away)
.WithMany()
.HasForeignKey(m => m.AwayId);
modelBuilder.Entity<Result>()
.HasOne(r => r.Match)
.WithOne()
.HasForeignKey<Result>(r => r.MatchId);
其中一个问题是来自 Match
的 WithMany
映射不正确。将其更改为 WithOne
- 尽管更正确 - 对问题没有任何影响。它已通过删除从 Result
到 Match
的关系映射得到修复。显然,这默默地映射了反向关系,选择两个关系之一朝向 Result
。因为(我假设)Entity Framework 会在指定一端后处理反向关系,所以可以(应该)将其排除以修复问题并保留所有导航。
为了完整性,最后的ModelBuilder
定义:
modelBuilder.Entity<Match>()
.HasOne(m => m.Home)
.WithOne()
.HasForeignKey(m => m.HomeId);
modelBuilder.Entity<Match>()
.HasOne(m => m.Away)
.WithOne()
.HasForeignKey(m => m.AwayId);