zoukankan      html  css  js  c++  java
  • EF查询之性能优化

    关于EF性能优化的讲解,推荐阅读下面的博文

    1.EF查询之性能优化:https://www.cnblogs.com/eggTwo/p/5959207.html
    2.Entity Framework 延伸系列目录:

    • a.Entity Framework 延伸系列目录
    • b.采用EntityFramework.Extended 对EF进行扩展(Entity Framework 延伸系列2)
    • c.EntityFramework执行存储过程中遇到的那些坑
    • d.EntityFramework的多种记录日志方式,记录错误并分析执行时间过长原因(系列4)
      https://www.cnblogs.com/GuZhenYin/p/5482288.html

    介绍EF性能优化前补充EF的优缺点:

    1.EF的优点:
    * (1)极大提高开发效率。EF是微软自己的产品,跟VS开发工具集成度比较好,开发中代码都是强类型的,写代码效率非常高,自动化程度非常高,采用命令式的编程。
    * (2)EF提供的模型设计器非常强大,不仅仅带来了设计数据库的革命,其附带的自动化生成模型代码的功能也极大地提高了开发和架构设计的效率。
    * (3)EF跨数据库支持是ORM框架的主要功能点之一,有着仅仅通过改变配置就可以做到跨数据库的能力,更换数据库非常方便。
    2.EF的缺点:
    * (1)EF性能不好,性能有损耗。(生成sql脚本阶段)在复杂查询的时候生成的SQL脚本效率不是很高。
    * (2)数据库端性能损耗是一样的,但是在将对象状态转换为SQL语句时会损失性能。
    
    

    一、EF性能优化

    1.延迟加载的开关
    • a.默认情况延迟加载是开启的,延迟加载的开启方式有两种:
    • (1)第一种是在dbcontext中设置
      public MyDbContext(System.Data.Common.DbConnection oConnection)
                : base(oConnection, true)
     {
                this.Configuration.LazyLoadingEnabled = true;         
      }
    
    • (2)第二种是在使用DbContext的时候设置
    using (var db = new Core.EF.MyDbContext())
    {
                        db.Configuration.LazyLoadingEnabled = false;
                        var classes= db.T_Student.Where(c => true).FirstOrDefault();
                        int a = 3;
    }
    
    • b.当我们不需要使用子表的时候可以关闭延迟加载
    using (var db = new Core.EF.MyDbContext())
    {
                        db.Configuration.LazyLoadingEnabled = false;
                        var classes= db.T_Student.Where(c => true).FirstOrDefault();
                        int a = 3;
    }
    

    • c.当我们需要使用子表的时候可以打开延迟加载
    using (var db = new Core.EF.MyDbContext())
    {
                        db.Configuration.LazyLoadingEnabled = true;
                        var classes= db.T_Student.Where(c => true).FirstOrDefault();
                        int a = 3;
    }
    

    2.延迟加载时使用Include提高性能
    • 使用inlude的两大前提
    • 1.开启延迟加载
    • 2.在使用Include的类上using System.Data.Entity
    (1)不使用include的情况
    #region 不使用include的情况,查询了6次
                        //当我们不需要使用子表的数据时,我们可以选择关闭延迟加载
                        db2.Configuration.LazyLoadingEnabled = true;//延迟加载
                        var students = db2.T_Student.Where(c=>true).Take(5).ToList();
                        foreach (var item in students)
                        {
                            var c = item.T_Classes;
                        }
    #endregion
    

    看出:查询了6次(1次T_Student,5次T_Classes)

    (2)使用include的情况
    #region 使用include的情况,只查询了一次(T_Student和T_Classes进行了连表查询)
                        //当我们不需要使用子表的数据时,我们可以选择关闭延迟加载
                        db2.Configuration.LazyLoadingEnabled = true;//延迟加载
                        var students1 = db2.T_Student.Where(c => true).Take(5).Include(c => c.T_Classes).ToList();
                        foreach (var item in students1)
                        {
                            var c = item.T_Classes;
                        }
    #endregion
    
    


    看出:查询了1次(T_Student和T_Classes连表查询)

    3.AsNoTracking提高查询性能
      var student3 = db2.T_Student.Where(c => c.Name == "李四50").Take(5).ToList();
      var student4 = db2.T_Student.Where(c => c.Name == "李四50").Take(5).AsNoTracking().ToList();
    
    • AsNoTracking的作用就是在查询的时候不做跟踪,这样查询的会更快,但是这样做会有一个缺陷:不能对查询的数据做修改操作
    4.多字段排序
         //错误的写法:age的排序会把name的排序冲掉
         var student5 = db2.T_Student.Where(c => c.Name == "李四50").OrderBy(c => c.Name).OrderBy(c => c.Age).AsNoTracking().ToList();
        //正确的写法:
        var student6 = db2.T_Student.Where(c => c.Name == "李四50").OrderBy(c => c.Name).ThenBy(c => c.Age).AsNoTracking().ToList();
    

    5.EF中使用sql
                        ///*
                        //  这种写法还支持将sql语句查询的结果集(DataSet和DataTable)
                        //  直接转换成对应的强类型集合(List<T>)
    
                        // */
    
                        //db2.Database.SqlQuery<T>("sql","parameters");
    
                        ///*
                        // 如果使用db.Database.SqlQuery<T>("sql语句")进行分页查询
                        // 的话,要注意避免内存分页
                        // */
    
                        ///*
                        // 错误的写法,内存分页
                        // 如果使用db.Database.SqlQuery<T>("sql语句")进行分页查询的话,要注意避免内存分页
                        // */
                        //var pageSize = 15;
                        //var pageIndex = 2;
                        //db2.Database.SqlQuery<T>("select * from T_Student").OrderByDescending(c=>c.CreateTime).Skip(pageSize*(pageIndex -1)).Take(pageSize).ToList();
                        ////这种写法会导致在内存中分页
    
    
                        ///*
                        // 正确的写法
                        // */
                        //string sql = "select * from T_Student";
                        //string orderBy = "CreateTime desc";
                        //StringBuilder sb = new StringBuilder();
                        //sb.Append(string.Format(@"select * from(select *,row_number() over (order by {0} as row from(", orderBy));
                        //sb.Append(sql);
                        //sb.Append(@") as t)as s where s.row between " +(pageIndex * pageSize -pageSize +1) + " and " +(pageIndex *pageSize));
                        //var list = db2.Database.SqlQuery<T>(sb.ToString()).ToList();
    
    
    6.存在性之Any
                  //测试班级表中是否包含'高中二班4'
                  bool a = db2.T_Classes.Where(c => c.Name == "高中二班4").Count() > 0;
                  bool b = db2.T_Classes.Count(c => c.Name == "高中二班4") > 0;
                  bool e = db2.T_Classes.Where(c => c.Name == "高中二班4").FirstOrDefault() != null;
                  bool d = db2.T_Classes.Any(c => c.Name == "高中二班4");
    
                  //一共上述4种写法
                  //结果:第1种写法和第二种写法生成的sql语句是一样的,
                  //第三种写法和第四种写法的耗时明显比第一种写法少???这个实际看到的是多!!!,还没研究明白!!!!!!!!
    
    

    7.多表查询
     ////等值连接Lambda写法
                        //var result1 = db2.T_Classes.Where(t => t.Money == 2000).Join(db2.T_Student, c => c.ID,
                        //    s => s.ClassesID, (c, s) => new {
                        //        CName = c.Name,
                        //        SName = s.Name
                        //    }).ToList();
                        ////等值连接Linq写法
                        //var resut2 = (from c in db2.T_Classes
                        //              join s in db2.T_Student
                        //              on c.ID equals s.ClassesID
                        //              where c.Money == 2000
                        //              select new
                        //              {
                        //                   CName =c.Name,
                        //                   SName = s.Name
                        //              }).ToList();
                        ////可以看出以上两种写法生成的sql语句是一样的
    
    
    
                        ////左(右)连接的写法
    
                        ////左外连接的写法
                        //var results = (from c in db2.T_Classes.Where(a => a.Money == 2000)
                        //               join s in db2.T_Student on c.ID equals s.ClassesID into temp
    
                        //               //临时表
                        //               from t in temp.DefaultIfEmpty()
                        //               select new
                        //               {
                        //                   CName = c.Name,
                        //                   SName = t.Name
    
                        //               }).ToList();
    
    
    8.分页查询封装
                         //单条件排序
                        var r1 = Repository.GetPagedEntitys<T_Classes, int>(db2, 1, 20, c => c.Deleted == false, false, c => c.ID);
                        //多条件排序
                        var r2 = Repository.GetPagedEntitys<T_Classes, int, bool>(db2,1,20,c=>c.Deleted ==false,false,c=>c.ID,true,c=>c.Deleted);
                        //sql查询转强类型
                        var r3 = Repository.GetPagedEntitysBySqlWhere<T_Classes>(db2, 1, 20, "and Deleted=0", "ID DESC");
                        //纯sql操作
                        var r4 = Repository.GetPagedTable(db2,1,20,"select * from T_Classes where Deleted=0","ID DESC");
    

    9.Expressions扩展
    /**
                        条件的拼接(当满足某个固定条件时才把对应的条件拼接出来) 
                        */
    
                        //原始的写法:
                        //模拟一系列条件
                        string name = "李四0";
                        int age = 0;
                        int pageSize = 20;
                        int pageIndex = 1;
                        ////原始写法如下:
                        //var query = db2.T_Student.Where(c=>c.Deleted == false);
                        //if (!string.IsNullOrEmpty(name))
                        //{
                        //    query = query.Where(c=>c.Name.Contains(name));
                        //}
                        //if (age !=0)
                        //{
                        //    query = query.Where(c => c.Age == age);
                        //}
    
                        //var list = query.OrderByDescending(c => c.ID).Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToList();
    
                        //无法和封装的分页类进行集成,返回的数据只有列表集合,没有总页数和总记录数
    
    
    
                        //所以对Linq.Expressions进行扩展                  
    
    
                        //多条件查询 +分页的极速简单写法(强烈推荐写法)
    
                        //利用扩展的Linq的写法
                        Expression<Func<T_Student, bool>> exp = c => true;
                        if (!string.IsNullOrEmpty(name))
                        {
                            exp = exp.And(c => c.Name.Contains(name));
                        }
                        if (age != 0)
                        {
                            exp = exp.And(c => c.Age == age);
                        }
                        var r9 = Repository.GetPagedEntitys<T_Student, int>(db2, 1, 20, exp, false, c => c.ID);
    

    以上说明是参考: https://www.cnblogs.com/eggTwo/p/5959207.html 这位大牛博主的博文做的,就附上对应demo下载地址,供大家学习:
    附:[EF性能优化demo]

  • 相关阅读:
    hdu 2553 N皇后问题(dfs)
    hdu 1043 Eight(双向bfs)
    牛人的ACM经验 (转)
    康托和逆康托展开(转)
    hiho Mission Impossible 6(模拟 未提交验证。。)
    数组越界也可以这么巧~~~
    poj 1679 The Unique MST(次小生成树)
    zoj 3204 Connect them(最小生成树)
    hdu 4463 Outlets(最小生成树)
    廖雪峰Java1-2程序基础-8字符和字符串
  • 原文地址:https://www.cnblogs.com/newcapecjmc/p/12845377.html
Copyright © 2011-2022 走看看