.NET Core/EF Core 2.0 升级后急切加载 "No coercion operator is defined between types"
Eager Loading "No coercion operator is defined between types" after .NET Core/EF Core 2.0 Upgrade
在 .NET Core 1.x 中,我们有一个如下所示的方法:
public async Task<(PaperRecord Component, PaperPointerRecord Pointer)> GetOneAsync(DbSet<PaperPointerRecord> paperPointerRecords,
int? paperId = null,
long? externalPaperId = null,
Expression<Func<PaperPointerRecord, bool>> filter = null)
{
var query = filter is null ? paperPointerRecords.AsQueryable() : paperPointerRecords.Where(filter);
if (paperId.HasValue)
query = query.Where(_ => _.PaperPointerId == paperId);
if (externalPaperId.HasValue)
query = query.Where(_ => _.ExternalId == externalPaperId);
var record = await query.Include(_ => _.Paper)
.ThenInclude(_ => _.PaperColors)
.Select(_ => new
{
PaperRecord = _.Paper,
PaperPointerRecord = _
})
.SingleOrDefaultAsync();
return !(record is null) ? (record.PaperRecord, record.PaperPointerRecord) : throw NewPaperRecordNotFoundException(paperId, externalPaperId);
}
这对我们很有用。将整个项目升级到所有.NET Core 2.0 & EF Core 2.0后,该方法抛出此异常:
System.InvalidOperationException occurred: No coercion operator is defined between types 'PaperPointerRecord' and 'PaperRecord'.
此块中出现此异常:
var record = await query.Include(_ => _.Paper)
.ThenInclude(_ => _.PaperColors)
.Select(_ => new
{
PaperRecord = _.Paper,
PaperPointerRecord = _
})
.SingleOrDefaultAsync();
如果我删除预加载并像这样设置,错误就会消失,但我也没有得到预期的结果:
var record = await query.Select(_ => new
{
PaperRecord = _.Paper,
PaperPointerRecord = _
})
.SingleOrDefaultAsync();
我已经为此检查了 Microsoft Documentation,但我没有看到那里显示任何表明我们在预先加载方面做错了什么。
Include
在这种情况下没有用,因为您正在返回一个投影并且 Include
s 被忽略(阅读关于被忽略的包括 here)。
如果 "intended results" 你的意思是你希望 record.PaperRecord.Paper
有一个值,只需将它包含在你的投影中; EF 将建立关系。
new
{
PaperRecord = _.Paper,
PaperPointerRecord = _,
PaperColor = _.Paper.PaperColor,
}
在 .NET Core 1.x 中,我们有一个如下所示的方法:
public async Task<(PaperRecord Component, PaperPointerRecord Pointer)> GetOneAsync(DbSet<PaperPointerRecord> paperPointerRecords,
int? paperId = null,
long? externalPaperId = null,
Expression<Func<PaperPointerRecord, bool>> filter = null)
{
var query = filter is null ? paperPointerRecords.AsQueryable() : paperPointerRecords.Where(filter);
if (paperId.HasValue)
query = query.Where(_ => _.PaperPointerId == paperId);
if (externalPaperId.HasValue)
query = query.Where(_ => _.ExternalId == externalPaperId);
var record = await query.Include(_ => _.Paper)
.ThenInclude(_ => _.PaperColors)
.Select(_ => new
{
PaperRecord = _.Paper,
PaperPointerRecord = _
})
.SingleOrDefaultAsync();
return !(record is null) ? (record.PaperRecord, record.PaperPointerRecord) : throw NewPaperRecordNotFoundException(paperId, externalPaperId);
}
这对我们很有用。将整个项目升级到所有.NET Core 2.0 & EF Core 2.0后,该方法抛出此异常:
System.InvalidOperationException occurred: No coercion operator is defined between types 'PaperPointerRecord' and 'PaperRecord'.
此块中出现此异常:
var record = await query.Include(_ => _.Paper)
.ThenInclude(_ => _.PaperColors)
.Select(_ => new
{
PaperRecord = _.Paper,
PaperPointerRecord = _
})
.SingleOrDefaultAsync();
如果我删除预加载并像这样设置,错误就会消失,但我也没有得到预期的结果:
var record = await query.Select(_ => new
{
PaperRecord = _.Paper,
PaperPointerRecord = _
})
.SingleOrDefaultAsync();
我已经为此检查了 Microsoft Documentation,但我没有看到那里显示任何表明我们在预先加载方面做错了什么。
Include
在这种情况下没有用,因为您正在返回一个投影并且 Include
s 被忽略(阅读关于被忽略的包括 here)。
如果 "intended results" 你的意思是你希望 record.PaperRecord.Paper
有一个值,只需将它包含在你的投影中; EF 将建立关系。
new
{
PaperRecord = _.Paper,
PaperPointerRecord = _,
PaperColor = _.Paper.PaperColor,
}