当被选为对象时;Linq To SQL是否仍然执行SQL查询中的逻辑

本文关键字:SQL 执行 查询 是否 对象 被选为 To Linq | 更新日期: 2023-09-27 18:18:10

假设我有以下简化的Linq查询,它将使用LinqToSQL对数据库运行:

public IEnumerable<MembershipDto> GetAllUserMemberships()
{
    return (from m in _workspace.GetDataSource<UserMembership>()
            join g in _workspace.GetDataSource<Group>()
                on m.GroupID equals g.GroupID
            join u in _workspace.GetDataSource<User>()
                on m.UserID equals u.UserID
            select 
                new MembershipDto
                {
                    GroupID = g.GroupID,
                    GroupName = g.Name,
                    UserID = u.UserID,
                    UserName = u.Name
                }
            ).Distinct()
             .OrderBy(x => x.GroupName)
             .ThenBy(x => x.UserName);
}

出于性能考虑,我希望这个查询尽可能多地在生成的SQL查询中运行;然而,我希望在Linq中维护业务逻辑,以便可以轻松地进行单元测试。

我的问题是,我不确定上面的查询停止在SQL中执行,并开始在内存中操作。

我的假设是,一旦数据被选择到new MembershipDto,它不再是在SQL中进行;因此,后续的OrderBy()ThenBy()Distinct()操作都发生在内存中。

但是OrderBy()产生的是IOrderedQueryable类型的集合,而不是IOrderedEnumerable类型的集合;这表明,查询可能仍然在SQL中完整地执行。

是我的假设是正确的,还是整个查询转换成SQL,如果是这样,为什么是这种情况?

当被选为对象时;Linq To SQL是否仍然执行SQL查询中的逻辑

看看生成的SQL。我很确信你的斜体假设是错误的。LINQ to SQL提供程序将认识到您的OrderByThenByDistinct操作只对SQL结果执行,因此它在将它们反序列化为对象之前完成对您选择的行的操作。只有当你试图对执行时数据库不可用的值进行操作时,查询的那一部分才会由LINQ to Objects执行。

如果在你的初始化器中你设置了一些属性的值,在查询结果中不可用,然后在OrderBy子句中使用它,它肯定会在内存中进行排序,因为没有其他方法。在本例中,select被转换为SQL SELECT,然后像往常一样调用OrderByDistinct。将所选内容转换为对象的操作完全独立于选择数据库中的列。对于SQL提供程序,您的查询与简单的选择语句没有什么不同,它构建一个表达式树,并在执行时将它可以转换为SQL。

相信您发布的所有代码将被转换成sql。MembershipDto()构造将映射到一个select语句。

当你的函数强制转换为IEnumerable并执行枚举器时,你将"退出"Linq to Sql并"进入"Linq to Objects。

如果你正在使用Linq to Sql进行开发,那么你绝对有必要拥有自己测试的工具。

我推荐LINQPad。你用c#编写代码,它会显示生成的SQL。

另一个解决方案是在数据上下文中记录生成的SQL:

#if DEBUG
        /// <summary>
        /// Code which runs when the data context is created; called from the constructor
        /// </summary>
        /// <remarks>Adds console and/or ASP.NET trace logger in DEBUG builds only</remarks>
        partial void OnCreated()
        {
            this.DebugBuildLogging();
        }
#endif

我还建议读一本关于LINQ的好书。你会得到多次的奖励。