实体框架核心:SQLite 中所有其他结果缺少相关数据



从数据库中检索数据时我遇到了一个奇怪的问题。这是一个从 .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);

这样做的一个问题是,来自MatchWithMany映射不正确。将其更改为WithOne- 虽然更正确 - 对问题没有影响。通过删除从ResultMatch的关系映射来修复它。显然,这默默地映射了反向关系,选择了两种关系中的一种对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);

相关内容

最新更新