在不同层级使用LINQ to SQL进行投影而不泄露IQueryable

在开发过程中,经常需要从数据库查询数据,并将这些数据投影到不同的层级。LINQ to SQL 提供了一种方便的方式来执行这些操作。然而,如果不小心处理,可能会导致IQueryable泄露,这将影响性能。本文将介绍如何在不同层级使用LINQ to SQL进行数据投影,同时避免泄露IQueryable。

LINQ to SQL中,通常使用如下方式进行数据查询和投影

var query = from c in Cars select new { c.carNo, c.eName };

这种方式只能在拥有“Cars”作为IQueryable的层级中使用。一旦将其返回为IList或IEnumerable,那么任何在其上的投影都将是LINQ to Entities,而不是LINQ to SQL,这意味着不会将投影发送到数据库。

好处

使用LINQ to SQL进行投影的主要好处包括:

  • 加快从SQL服务器返回的结果速度。
  • 减少需要通过线路传输的数据量。
  • 减少或消除为每个实体(即表)创建多个DTO的需求,通过仅请求所需的字段,并将完整的域实体返回到模型中,但只填充那些字段。
  • 每个功能一个过程,但具有不同的投影,而不是每个投影多个过程。

当在处理许多组合框和列表时,会感觉到“这帮助了很多”。

解决方案

为了解决这个问题,可以通过动态编译代码来实现。将所需的字段列表发送到代码片段字符串,该字符串将被编译,然后调用编译后的函数以对任何实体进行投影。

public static IEnumerable<T> ProjectOn<T>(IQueryable query, string fieldsList) where T : class { // 编译代码并执行 }

这种方法允许在不同的层级中使用LINQ to SQL进行投影,同时避免泄露IQueryable。

示例

以下是一个示例解决方案,它包含多个项目,展示了如何在不同层级使用LINQ to SQL进行投影:

  • 不带投影的列表:列出大多数POCO实体字段,因此发送到数据库的SQL语句包含所有字段。
  • 编译时带投影的列表:在编译时对一些字段进行投影,因此发送到数据库的SQL语句只包含所需的字段,但必须为每个投影定义一个函数,并且只有在具有EntityFramework引用的层(如Repository)中。
  • 运行时带投影的列表:在编译时对一些字段进行投影,因此发送到数据库的SQL语句只包含所需的字段,并且只需要一个函数。

主要功能位于“LinqProjectionC.LinqProjection”类中:

public class LinqProjection { static string codeIEnumerable = @" using System; using System.Collections.Generic; using System.Linq; namespace UserClasses { public class RuntTimeClass { public static IEnumerable<%TypeName%> anyFunction(IQueryable<%TypeName%> query) { var enumerable = query.Select(c => new { %fieldsList% }).ToList(); var queryEntities = from c in enumerable select new %TypeName%() { %fieldsList% }; return queryEntities.ToList(); } } }"; }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485