当我尝试编译这个测试代码时:
using Microsoft.EntityFrameworkCore;
using var db = new InventoryContext();
await db.AddAsync<Item>(new() { Name = "Table", Description = "A wooden office Table with a cup holder", Type = ItemType.Furniture });
await db.SaveChangesAsync();
Console.WriteLine("Showing all entries:");
Func<InventoryContext, IAsyncEnumerable<Item>> compiled = EF.CompileAsyncQuery((InventoryContext db) => from item in db.Items orderby item.Id select item);
IAsyncEnumerable<Item> items = compiled(db);
await foreach (Item item in items)
{
Console.WriteLine(item.Id);
Console.WriteLine(item.Name);
Console.WriteLine(item.Type);
Console.WriteLine(item.Description is null ? "*no description*" : item.Description);
Console.WriteLine();
}
它告诉我“System.Func
将第 10 行更改为
Func<InventoryContext, IAsyncEnumerable<Item>> compiled = EF.CompileAsyncQuery((InventoryContext db) => db.Items.OrderBy(x => x.Id));
它也不会起作用,只有在添加 .Select(x=>x) 或删除 orderby 部分时它才会起作用。有人可以解释为什么(至少对我来说是这样)有序语句不能用于编译查询吗?
您遇到的问题与查询表达式返回的类型有关。当你在查询中使用 orderby 时,它返回一个 IOrderedQueryable,它不直接与 IAsyncEnumerable 兼容。
但是,当你使用.OrderBy(x => x.Id)然后添加.Select(x => x)或者去掉orderby部分时,返回类型变为IQueryable,兼容IAsyncEnumerable。这就是为什么在这些情况下你不会收到类型不匹配错误的原因。
要解决此问题并在已编译查询中使用 orderby 部分,您可以像这样简单地将结果转换为 IQueryable:
Func<InventoryContext, IAsyncEnumerable<Item>> compiled = EF.CompileAsyncQuery((InventoryContext db) =>
(from item in db.Items orderby item.Id select item) as IQueryable<Item>);
或者,使用方法语法:
Func<InventoryContext, IAsyncEnumerable<Item>> compiled = EF.CompileAsyncQuery((InventoryContext db) =>
db.Items.OrderBy(x => x.Id) as IQueryable<Item>);
这将允许您在编译查询中保留 orderby 部分,而不会遇到类型不匹配错误。