我有一个数据模型,其中'Top'对象具有介于0和N'Sub'对象之间.在SQL中,这是通过外键实现的dbo.Sub.TopId
.
var query = context.Top
//.Include(t => t.Sub) Doesn't seem to do anything
.Select(t => new {
prop1 = t.C1,
prop2 = t.Sub.Select(s => new {
prop21 = s.C3 //C3 is a column in the table 'Sub'
})
//.ToArray() results in N + 1 queries
});
var res = query.ToArray();
Run Code Online (Sandbox Code Playgroud)
在Entity Framework 6(延迟加载关闭)中,此Linq查询将转换为单个 SQL查询.结果将被完全加载,因此res[0].prop2
将被IEnumerable<SomeAnonymousType>
填充.
使用EntityFrameworkCore(NuGet v1.1.0)时,子集合尚未加载且类型为:
System.Linq.Enumerable.WhereSelectEnumerableIterator<Microsoft.EntityFrameworkCore.Storage.ValueBuffer, <>f__AnonymousType1<string>>.
Run Code Online (Sandbox Code Playgroud)
在迭代数据之前,不会加载数据,从而导致N + 1个查询.当我添加.ToArray()
到查询(如注释中所示)时,数据被完全加载到var res
,使用SQL分析器但是显示这不再在1个SQL查询中实现.对于每个"Top"对象,执行"Sub"表上的查询.
第一次指定.Include(t => t.Sub)
似乎没有改变任何东西.匿名类型的使用似乎也不是问题,替换new { …
When working with an IEnumerable<T>
there are the build-in extension methods from the System.Linq
namespace such as Skip
, Where
and Select
to work with.
When Microsoft added IAsyncEnumerable
in C#8 did they also add new Linq methods to support this?
I could of course implement these methods myself, or maybe find some package which does that, but I'd prefer to use a language-standard method if it exists.