视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
LINQtoSql系列四性能优化总结
2020-11-09 10:08:31 责编:小采
文档

Linq to sql 是一个代码生成器和ORM工具,他自动为我们做了很多事情,这很容易让我们对他的性能产生怀疑。但是也有几个测试证明显示在做好优化的情况下,linq to sql的性能可以提升到ado.net datareader性能的93%。 因此我总结了Linq to sql的10个性能提升点

Linq to sql 是一个代码生成器和ORM工具,他自动为我们做了很多事情,这很容易让我们对他的性能产生怀疑。但是也有几个测试证明显示在做好优化的情况下,linq to sql的性能可以提升到ado.net datareader性能的93%。
因此我总结了Linq to sql的10个性能提升点,来优化其查询和修改的性能。

1. 不需要时要关闭 DataContext的ObjectTrackingEnabled 属性

using (NorthwindDataContext db= new NorthwindDataContext()) { db.ObjectTrackingEnabled = false; }

关闭这个属性会使linq to sql停止对对象的标识管理和变化跟踪。但值得注意的是关闭ObjectTrackingEnabled 意味着也将DeferredLoadingEnabled属性设置为false,当访问相关表时会返回null。


2. 不要把所有的数据对象都拖到一个DataContext中

一个DataContext代表一个工作单元,并非整个数据库。如果几个数据库对象之间没有关系,服务器,或者在程序中用不到的数据库对象(例如日志表,服务器,批量操作表等等),让这些对象消耗内存空间和DataContext对象跟踪服务是完全没有必要的。
建议将所有的数据库对象按工作单元分给几个DataContext来处理。你也可以通过构造函数配置这些DataContext使用相同的数据库连接,这样也可以发挥据库连接池的用途。


3. CompiledQuery --- 有必要就得用

在创建一个linq to sql表达式并将它转换成对应的sql语句执行的过程,需要几个关键的步骤
1) 创建表达式树
2) 转换成sql
3) 运行sql语句
4) 取回数据
5) 将数据转换成对象

很显然,当我们一遍又一遍的执行相同的查询时,上面1),2)两个步骤重复执行是在浪费时间。使用System.Data.Linq命名空间下的CompiledQuery类的Compile方法可以避免这种浪费。
请看下面的使用示例:

Func> func = CompiledQuery.Compile> ((NorthwindDataContext context) => context.Categories. Where(cat => cat.Products.Count > 5));

func变量现在是一个已经编译后的查询,他只需要在第一次运行时编译一次,就可以重复使用,虚拟主机,现在我们将其存储到一个静态类中,如下所示:

Utility class to store compiled queries QueriesUtility { Gets the query that returns categories with more than five products. Func> GetCategoriesWithMoreThanFiveProducts { get { Func> func = CompiledQuery.Compile> ((NorthwindDataContext context) => context.Categories. Where(cat => cat.Products.Count > 5)); return func; } } }

如何使用它呢,请看下面的代码片段:

using (NorthwindDataContext context = new NorthwindDataContext()) { QueriesUtility.GetCategoriesWithMoreThanFiveProducts(context); }


4. 使用DataLoadOptions.AssociateWith设置仅从数据库中取需要的数据
5. 仅在需要时打开积极并发控制,换句话说如果不需要请将列的UpdateCheck属性设置为UpdateCheck.Never,这样在更新和删除时可以减少不必要的条件判断

[Column(Storage=“_Description”, DbType=“NText”, UpdateCheck=UpdateCheck.Never)] public string Description { get { return this._Description; } set { if ((this._Description != value)) { this.OnDescriptionChanging(value); this.SendPropertyChanging(); this._Description = value; this.SendPropertyChanged(“Description”); this.OnDescriptionChanged(); } } }

6. 经常设置DataContext.Log查看linq to sql执行时使用的sql,分析取回的数据是否刚好够用

using (NorthwindDataContext context = new NorthwindDataContext()) { context.Log = Console.Out; }

7. 仅在有必要时使用Attach方法

在linq to sql中对象附加是一个的非常好用的机制,但是什么事情都不是免费的。当在DataContext中Attach对象时,就意味着过一段时间你会使用这个对象,DataContext会给这个对象做“马上要做修改的”标记。
但是有时候Attach并非必要,例如使用AttachAll去附加一个集合,这个集合中的元素并非都会发生变化。


8. 注意实体标识管理的开销

在一个非只读的DataContext中,对象一直会被跟踪,因此要知道在非直觉的情况下也可能会导致DataContext做对象跟踪,请看下面的代码:

using (NorthwindDataContext context = new NorthwindDataContext()) { var a = from c in context.Categories select c; }

非常简单,就是一个最基本的linq查询,让我们再看下另一个语句

using (NorthwindDataContext context = new NorthwindDataContext()) { var a = from c in context.Categories select new Category { CategoryID = c.CategoryID, CategoryName = c.CategoryName, Description = c.Description }; }

下载本文
显示全文
专题