c# - LINQ 到 SQL : how to select specific fields conditionally into DTOs (performance)

标签 c# .net performance linq linq-to-sql

LINQ to SQL 非常棒,但在某些情况下会适得其反。对于我的案例,它适得其反。

我有一个 StudentServiceDm,它映射到一个包含 40 个字段的 StudentService 表。我在表中有 10-20 百万个服务。客户的要求是,他们需要将所有服务从应用程序导出到excel,同时只选择他们当时想要的字段。

据我所知,如果我这样做

IQueryable<StudentServiceDm> serviceQuery = GetListQuery();
List<StudentServiceDto> dtos = serviceQuery.Select(m => new StudentServiceDto
{
    Id = m.Id,
    Name = m.Name,
}).ToList();

然后这转化为只选择我需要的字段的SQL

SELECT Id, Name FROM StudentService

这通过减少需要选择的字段数量来节省性能。

但在我的例子中,我需要允许用户有条件地选择这样的字段,所以我这样做:

IQueryable<StudentServiceDm> serviceQuery = GetListQuery();

List<StudentServiceDto> dtos = serviceQuery.Select(m => new StudentServiceDto
            {
                Id = (options.ShowId) ? m.Id : null,
                Name = (options.ShowName) ? m.Name,
                StudentFirstName = (options.ShowFirstName) ? m.Student.FirstName : null,
                StudentLastName = (options.ShowLastName) ? m.Student.LastName : null,
                StudentServiceType = (options.ShowType) ? m.StudentServiceType.Name : null,
                StudentServiceSubType = (options.ShowSubType) ? m.StudentServiceSubType.Name : null,
                Date = (options.ShowDate) ? m.Date : null,
                // alot more assignments .....
            }).ToList();

但是,这会转化为类似这样的 SQL 查询(根据 SQL Profiler:

SELECT 
    CASE WHEN (@p__linq__1 = 1) THEN [Project2].[Date] END AS [C1], 
    CASE WHEN (@p__linq__2 = 1) THEN [Project2].[Name] END AS [C2], 
    CASE WHEN (@p__linq__3 = 1) THEN [Project2].[StudentServiceTypeId] END AS [C3], 
    CASE WHEN (@p__linq__4 = 1) THEN [Project2].[StudentServiceSubTypeId] END AS [C4], 
    CASE WHEN (@p__linq__5 = 1) THEN [Project2].[Date] END AS [C5], 
    // ..... more fields
    FROM * // 

它在每个字段上设置一个条件来检查它是否应该检索......实际上这个查询的性能几乎与所有字段都被选中一样。

我要实现的是,如果用户只选择选择NameDate,那么翻译后的SQL应该只有

SELECT Name, Date FROM StudentService

经过一些性能分析,这2套语句的性能相差3-4倍左右。

有专家意见吗?

最佳答案

您可以在运行时创建与您在 .Select() 语句中输入的内容完全对应的 Linq 表达式,这不是很简单。我从来没有专门为 Linq to SQL 做过,但我不明白为什么它不起作用。类似于 How do I dynamically create an Expression<Func<MyClass, bool>> predicate?但我当然建议先阅读文档以熟悉表达式。

关于c# - LINQ 到 SQL : how to select specific fields conditionally into DTOs (performance),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43841081/

相关文章:

c# - 如何设置.csproj 的根目录?

c# - 如何使用 C#-Unity 将 Json 文件转换为字典

.NET 相当于 Qt 图形 View 框架吗?

.net - 信任自签名证书以验证服务器(Windows 上的 .NET 客户端)

django - 如何在 Web 请求期间限制数据库查询时间?

mysql - 在 mysql 表中存储多个范围以使查询更快/更容易

c# - 带有每个项目的详细信息行的 Gridview

c# - 将 LINQ 序列中的项目发送到返回 void 的方法

c# - 在 x86 系统上编译 C# .NET x64 二进制文件

javascript - JavaScript 中的性能内存管理