首页 > 解决方案 > 为什么在 linq-to-entity 查询中使用我的 C# 扩展方法将数据库项加载到内存中,而不是在数据库服务器上运行?

问题描述

我创建了以下简单的扩展方法:

public static IQueryable<TSource> DistinctBy<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector)
{
    return source.GroupBy(keySelector)
                 .Select(g => g.FirstOrDefault())
                 .AsQueryable();
}

我的问题似乎是代码实际上将数据库行加载到内存中并尝试在内存中执行操作,而不是执行 Linq-To-Entities 应该执行的操作并将查询转换为 SQL。

可以在上面看到我的扩展方法没有做任何不能翻译成 SQL 的事情,那么为什么不这样做呢?

以下两行代码应该是等效的,但第一行在 <200ms 内执行,而另一行运行大约 20 分钟,然后抛出内存不足异常:

// Executes in less than 200ms.
var test_1 = dbContext.SomeTable.GroupBy(row => new { row.SomeColumn, row.SomeOtherColumn })
                                .Select(g => g.FirstOrDefault())
                                .Tolist();
// The line below takes some 20 minutes to eventually throw an out of memory exception.
// Notice I'm not even calling ToList().
var test_2 = dbContext.SomeTable.DistinctBy(row => new { row.SomeColumn, row.SomeOtherColumn });

请注意,此扩展方法只是一个示例。不使用它而是直接使用方法内部定义的代码相对容易。我这么说是因为我不是在问如何制作“DistinctBy”方法。相反,我要问的是如何编写仅使用其他“可翻译”方法以避免代码重复的扩展方法。

我知道我只能使用 EF 提供者提供的扩展方法,但本质上就是我正在做的事情。我不能让它知道我的方法可以直接翻译成SQL,GroupBy方法是如何做到的?

标签: c#entity-frameworklinq-to-entitiesextension-methods

解决方案


推荐阅读