无法翻译查询
Query cannot be translated
我有以下 class:
class document
{
int Id;
List<Tag> Tags;
}
class Tag
{
int Id;
}
我想获取至少具有用户选择的标签之一的所有文档。
我编写了以下 linq 查询:
List<int> tagIds = tags.Select (x => x.Id).ToList ();
query.Where (doc => tagIds.Any (x => doc.Tags.Select (y => y.Id).Contains (x)));
如果我针对文档列表执行它,它会起作用,但如果我使用 efcore 5 针对 sqlite 数据库执行它,我会收到以下错误:
System.InvalidOperationException: 'The LINQ expression 'DbSet<DemaDocument>()
.Where(d => __tagIds_0
.Any(x => DbSet<Dictionary<string, object>>("DemaDocumentDemaTag")
.Where(d0 => EF.Property<Nullable<int>>(d, "Id") != null && object.Equals(
objA: (object)EF.Property<Nullable<int>>(d, "Id"),
objB: (object)EF.Property<Nullable<int>>(d0, "DocumentsId")))
.Join(
inner: DbSet<DemaTag>(),
outerKeySelector: d0 => EF.Property<Nullable<int>>(d0, "TagsId"),
innerKeySelector: d1 => EF.Property<Nullable<int>>(d1, "Id"),
resultSelector: (d0, d1) => new TransparentIdentifier<Dictionary<string, object>, DemaTag>(
Outer = d0,
Inner = d1
))
.Select(ti => ti.Inner.Id)
.Any(p => p == x)))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.'
如何使用 Fluent LINQ 重写查询以使其正常工作?是否可能,或者我是否必须检索内存中的文档然后 运行 查询?这并不理想,因为文档会随着时间的推移而增长...
提前致谢
.Contains
应翻译为 SQL IN
语句,即 x IN 1, 2, 3
。这要求列表是常量。在您的示例中,doc.Tags.Select (y => y.Id)
对于每个文档都是唯一的,因此无法将其转换为常量列表。
你所做的或多或少是检查两个列表是否相交,所以我们应该能够颠倒两个列表的顺序:
query.Where(doc => doc.Tags.Any(x => tagIds.Contains(x.Id)))
现在 tagIds 对于查询是常量,.Contains
语句可以正确翻译。
我有以下 class:
class document
{
int Id;
List<Tag> Tags;
}
class Tag
{
int Id;
}
我想获取至少具有用户选择的标签之一的所有文档。
我编写了以下 linq 查询:
List<int> tagIds = tags.Select (x => x.Id).ToList ();
query.Where (doc => tagIds.Any (x => doc.Tags.Select (y => y.Id).Contains (x)));
如果我针对文档列表执行它,它会起作用,但如果我使用 efcore 5 针对 sqlite 数据库执行它,我会收到以下错误:
System.InvalidOperationException: 'The LINQ expression 'DbSet<DemaDocument>()
.Where(d => __tagIds_0
.Any(x => DbSet<Dictionary<string, object>>("DemaDocumentDemaTag")
.Where(d0 => EF.Property<Nullable<int>>(d, "Id") != null && object.Equals(
objA: (object)EF.Property<Nullable<int>>(d, "Id"),
objB: (object)EF.Property<Nullable<int>>(d0, "DocumentsId")))
.Join(
inner: DbSet<DemaTag>(),
outerKeySelector: d0 => EF.Property<Nullable<int>>(d0, "TagsId"),
innerKeySelector: d1 => EF.Property<Nullable<int>>(d1, "Id"),
resultSelector: (d0, d1) => new TransparentIdentifier<Dictionary<string, object>, DemaTag>(
Outer = d0,
Inner = d1
))
.Select(ti => ti.Inner.Id)
.Any(p => p == x)))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.'
如何使用 Fluent LINQ 重写查询以使其正常工作?是否可能,或者我是否必须检索内存中的文档然后 运行 查询?这并不理想,因为文档会随着时间的推移而增长...
提前致谢
.Contains
应翻译为 SQL IN
语句,即 x IN 1, 2, 3
。这要求列表是常量。在您的示例中,doc.Tags.Select (y => y.Id)
对于每个文档都是唯一的,因此无法将其转换为常量列表。
你所做的或多或少是检查两个列表是否相交,所以我们应该能够颠倒两个列表的顺序:
query.Where(doc => doc.Tags.Any(x => tagIds.Contains(x.Id)))
现在 tagIds 对于查询是常量,.Contains
语句可以正确翻译。