Linq 优化
- 了解LINQ执行流程
当我们执行LINQ查询时,完成以下步骤
• LINQ引擎
o 检查LINQ查询中的语法错误
o 将上述查询转换为SQL语句
o 将SQL语句传递给SQL Engine以执行。
• 查询执行计划是由SQL引擎构建的,查询已准备就绪。
• 查询被激发到数据库中。
- 避免使用Include子句
避免将Include子句与实体用作导航属性,因为它将检索表值以及关系信息。 这些会降低查询性能。 而是使用联接并使用自定义模型仅检索所需的数据。
包括:
List
.Include(“VendorDetails”) select e;
带联接(建议):
List
From prod in _context.Products join desp in _context.DespatchInfo on prod.ProdId
equals desp.prodid join vendor in _context.VendorDetails on prod.ProdId equals vendor.ProdId
select new ProductModel(){dataToSelect}
- 仅检索您需要的记录数
一个可以写这样选择COL1查询,COL2 ,......从表名,即使他/她可能不是需要所有行的结果集。
就像在学生列表的情况下,如果应用分页;无需一次获取所有记录,因为只有少数几个要显示在页面大小和页面编号上。因此,在这种情况下,可以使用以下实践。
即
private List
return context.Items.Take<Item>(pageSize).Skip<Item>(pageIndex * pageSize).ToList();
- 使用编译查询
当我们经历了LINQ执行流程时;它需要许多相关的步骤来运行LINQ查询;但是,如果我们想使用不同的参数集频繁触发结构相似的LINQ查询,我们可以使用编译查询。如果下一次执行,它将直接触发查询,而无需重新编译。
编译后的查询被声明为静态查询,因此它只能被编译一次,其他线程可以重用它。否则,它将不会在应用程序级别进行缓存,这使其比普通的LINQ查询更耗时。
当我们使用编译查询时,对后续调用的查询将直接执行(第一次执行后),而无需编译并再次生成执行计划。由于这些原因,编译后的查询运行得更快,并在后续执行中提高了性能。
何时使用
当使用结构相似的查询频繁获取结果以在后续执行中提高查询性能时,可以使用它。
也就是说,我们想按ID来获取学生-在这里,我们按ID来获取Student,此查询肯定会经常被触发。因此,在这种情况下,首选编译查询。
什么时候不使用
如果没有重复触发查询,则不建议使用此查询,因为它具有更多的关联成本,并且需要更多时间进行首次执行。
.NET 4.5及更高版本– LINQ查询被自动缓存,即使在给定情况下使用编译查询也更有效。
- Contains – 需要更多时间,请改用Join
在某些情况下,Contains子句可能比联接花费更多的时间来执行。因此,建议在这种情况下使用联接(尤其是在复杂查询中)
- 中断大型和/或复杂的LINQ查询
将复杂的查询分为较小但较简单的查询将使它们比单个查询执行得更快。它将划分/除去复杂的联接/其他逻辑,因为单个操作将消耗更多的时间来执行。
- 使用Any()代替Count()
我们通常使用Count()> 0来检查是否存在具有特定条件的项目。 Any()仅检查第一次迭代并返回true或false。 在内存中收集的情况下,任何人都不会有太多好处,但是在延迟执行的情况下,Any()比Count()更可取
8. 使用FirstOrDefault / SingleOrDefault时检查NULL
First OrDefault / SingleOrDefault也可以返回NULL值。在这种情况下,直接从对象读取属性会引发NULL引用异常。因此,在这种情况下,建议在访问前检查NULL值。
- 避免滥用隐式类型变量(var )
“ var ”关键字=编译器将确定并分配最合适的类型。但这会影响其他开发人员。他们可能会觉得很难理解。仅当类型不可用/未知/使用匿名类型时才应使用它。它也可以用于无法由开发人员推断类型的LINQ查询中。这也可能会降低性能。
- 延期执行
通过使用 toList ()立即枚举结果集,避免LINQ查询的延迟执行。这样可以防止多次调用数据库。延迟执行仅在有意义时使用。需要围绕它定义一些标准
- 对象引用而不是实例
当只需要传递引用时,请避免对对象实例使用构造函数,实例的多次定义会创建大量未使用的内存,最终导致性能降低和内存利用率高。相反,我们可以使用变量声明(无需使用构造函数来创建实例)。
- 循环中的LINQ查询
在LINQ中使用循环时,请避免在循环中使用LINQ查询,因为大多数查询都返回列表,如果不加以控制,可能会在短时间内导致大量内存使用。 而是尝试在循环外部创建条件列表,然后在循环内部进行操作(请记住何时从列表中删除/删除列表以及何时使用将状态标记为已删除)。。
- LINQ查询和对象
在同一个父集合上使用LINQ查询时,结果集将返回一个新的列表集合,该列表集合引用(指向)父集合中的对象。 新列表中对象的任何更改都会更改父对象及其所有派生子集合中对象的值/状态。