从数据库中检索数据时我遇到了一个奇怪的问题。这是一个从 .NET Core 1.0 升级到 .NET Core 2.1 的项目。一切都在事先工作,但是升级在加载相关数据时有一些奇怪的副作用。使用的确切版本是 .NETCore.app 的 2.1;2.1.4 for AspNetCore,2.1.4 for EntityFrameworkCore(.Sqlite(。
可以使用以下模型来表示问题。插入时,首先添加一个不带相关Result
实体的Match
。然后,创建每个Result
,最后使用这些实例再次更新Match
。这就是Match
中可空 ID fiels 的原因。
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)
(并检查结果时,每隔一个结果都会丢失相关数据。这似乎只发生在这些表格上,所以我的猜测是由于模型的双向性而误入歧途。
检查器显示如下所示的结果。应该注意的是,两个连续结果的集合总是指向相同的Match
。
results
- [0]
Id = 1000
Match = Null
- [1]
Id = 1001
Match = <Match object>
- [2]
Id = 1002
Match = Null
- [3]
Id = 1003
Match = <Match object>
等等。我在将数据插入这些表中时也遇到了麻烦(弹出了类似的问题(,但此时让我们将其排除在此问题的范围之外。
回答我自己的问题:问题出在关系映射上。有几个相关的问题恰好与我的问题相匹配,但通常建议创建其他字段以更好地描述映射。由于数据库架构不会更改,因此不是一个选项。
作为旁注,这个问题与SQLite没有太大关系。然而,奇怪的是,事情曾经像问题中描述的那样工作。我没有调查导致这种情况的原因,但看起来 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
.正如(我假设(实体框架在指定一端后处理反向关系一样,这可以(应该(被省略以修复问题并保留所有导航。
为了完整起见,最终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);