• == 解决 EF where<T>(func) 查询的一个性能问题


    https://www.cnblogs.com/xiaokangufo/p/3901402.html

    前两年帮朋友 做了个网吧管理软件,采用动软的三层架构 sql语句生成的。最近因功能变更 要改动,而我这段正在做asp.net mvc +ef+autofac的一个电商网站。索性 就把原来的底层全重新了套用了我现在的架构 EF6.0+autofac+三层架构,上层的asp.net没有变。改完后发现交班页面打开巨慢。

       

    跟踪EF生成的sql语句   发现生成的sql 有问题,查找的全表,而全表有近10万条的数据。

    继续跟踪数据库的耗时查询 发现确实是这条语句占时间

    为什么会这样呢,我在查询里做条件搜索了,为啥 结果不对呢?

    贴出 BaseRepository.cs 的代码

    public class BaseRepository<T> :IDBbase<T>  where T : class
        {
            //实例化EF框架
           protected skdbContext db = new skdbContext();
    
            //添加
            public T AddEntities(T entity)
            {
                db.Entry<T>(entity).State = EntityState.Added;
                db.SaveChanges();
                return entity;
            }
    
            //修改
            public bool UpdateEntity(T entity)
            {
                db.Set<T>().Attach(entity);
                db.Entry<T>(entity).State = EntityState.Modified;
                return db.SaveChanges() > 0;
            }
    
            //修改
            public bool DeleteEntities(T entity)
            {
                db.Set<T>().Attach(entity);
                db.Entry<T>(entity).State = EntityState.Deleted;
                return db.SaveChanges() > 0;
            }
    
            //查询
            public IQueryable<T> LoadEntities(Func<T, bool> wherelambda)
            {
                return db.Set<T>().Where<T>(wherelambda).AsQueryable();
            }
            //查询单个
            public T LoadEntitie(Func<T, bool> wherelambda)
            {
                return db.Set<T>().FirstOrDefault<T>(wherelambda);
            }
    
            //分页
            public IQueryable<T> LoadPagerEntities<S>(int pageSize, int pageIndex, out int total,
                Func<T, bool> whereLambda, bool isAsc, Func<T, S> orderByLambda)
            {
                var tempData = db.Set<T>().Where<T>(whereLambda);
    
                total = tempData.Count();
    
                //排序获取当前页的数据
                if (isAsc)
                {
                    tempData = tempData.OrderBy<T, S>(orderByLambda).
                          Skip<T>(pageSize * (pageIndex - 1)).
                          Take<T>(pageSize).AsQueryable();
                }
                else
                {
                    tempData = tempData.OrderByDescending<T, S>(orderByLambda).
                         Skip<T>(pageSize * (pageIndex - 1)).
                         Take<T>(pageSize).AsQueryable();
                }
                return tempData.AsQueryable();
            }
        }
    View Code

    调用代码 

    return jiaobanitem.LoadEntities(t => t.JiaoBanID == jiaobanID && t.GoodsID == GoodsID).FirstOrDefault();

    参考 nopCommerce  修改baserepository

    public class EFRepository<T> : IRepository<T> where T : class
        {
            //实例化EF框架
           //protected YaFeiNetContext db = new YaFeiNetContext();
           private DbContext _context;
           private IDbSet<T> _entities;
    
           public EFRepository(DbContext context)
           {
               this._context = context;
           }
    
    
            //添加
            public virtual T AddEntities(T entity)
            {
                try
                {
                    if(entity==null)
                        throw new ArgumentNullException("entity");
    
                    this.Entities.Add(entity);
                    this._context.SaveChanges();
                    return entity;
                }
                catch(DbEntityValidationException dbEx)
                {
                    var msg = string.Empty;
                    foreach(var validationErrors in dbEx.EntityValidationErrors)
                        foreach (var validationError in validationErrors.ValidationErrors)
                            msg += string.Format("Property:{0} Error:{1}", validationError.PropertyName, validationError.ErrorMessage) + Environment.NewLine ;
    
                    var fail = new Exception(msg,dbEx);
                    throw fail;
                }
            }
    
            //修改
            public virtual bool UpdateEntities(T entity)
            {
                try
                {
                    if (entity == null)
                        throw new ArgumentNullException("entity");
    
    
                   // this.Entities.Attach(entity);
                   // _context.Entry<T>(entity).State = EntityState.Modified;
                    return this._context.SaveChanges() > 0;
                }
                catch (DbEntityValidationException dbEx)
                {
                    var msg = string.Empty;
                    foreach (var validationErrors in dbEx.EntityValidationErrors)
                        foreach (var validationError in validationErrors.ValidationErrors)
                            msg += string.Format("Property:{0} Error:{1}", validationError.PropertyName, validationError.ErrorMessage) + Environment.NewLine;
    
                    var fail = new Exception(msg, dbEx);
                    throw fail;
                }
    
            }
    
            //修改
            public virtual bool DeleteEntities(T entity)
            {
                try
                {
                    if (entity == null)
                        throw new ArgumentNullException("entity");
    
                    //db2.Set<T>().Attach(entity);
                    //db2.Entry<T>(entity).State = EntityState.Deleted;
                    this.Entities.Remove(entity);
                    return this._context.SaveChanges() > 0;
                }
                catch (DbEntityValidationException dbEx)
                {
                    var msg = string.Empty;
                    foreach (var validationErrors in dbEx.EntityValidationErrors)
                        foreach (var validationError in validationErrors.ValidationErrors)
                            msg += string.Format("Property:{0} Error:{1}", validationError.PropertyName, validationError.ErrorMessage) + Environment.NewLine;
    
                    var fail = new Exception(msg, dbEx);
                    throw fail;
                }
    
    
            }
    
            //查询
            public virtual IQueryable<T> LoadEntities(Func<T, bool> wherelambda)
            {
                return this.Entities.Where<T>(wherelambda).AsQueryable();
            }
            //查询单个
            public virtual T LoadEntitie(Func<T, bool> wherelambda)
            {
                return this.Table.Where(wherelambda).FirstOrDefault();
            }
           /// <summary>
           /// 根据主键查找
           /// </summary>
           /// <param name="id"></param>
           /// <returns></returns>
            public virtual T GetById(object id)
            {
                return this.Entities.Find(id);
            }
    
    
    
    
            //分页
            public virtual IQueryable<T> LoadPagerEntities<S>(int pageSize, int pageIndex, out int total,
                Func<T, bool> whereLambda, bool isAsc, Func<T, S> orderByLambda)
            {
    
                var tempData = this.Entities.Where<T>(whereLambda);
    
                    total = tempData.Count();
    
                    //排序获取当前页的数据
                    if (isAsc)
                    {
                        tempData = tempData.OrderBy<T, S>(orderByLambda).
                              Skip<T>(pageSize * (pageIndex - 1)).
                              Take<T>(pageSize).AsQueryable();
                    }
                    else
                    {
                        tempData = tempData.OrderByDescending<T, S>(orderByLambda).
                             Skip<T>(pageSize * (pageIndex - 1)).
                             Take<T>(pageSize).AsQueryable();
                    }
                    return tempData.AsQueryable();
    
    
    
            }
    
            protected virtual IDbSet<T> Entities
            {
                get
                {
                    if (_entities == null)
                        _entities = _context.Set<T>();
                    return _entities;
                }
            }
    
    
            public virtual IQueryable<T> Table
            {
                get { return this.Entities; }
            }
    
    
        }
    View Code

    同时修改调用代码 为

    return jiaobanitem.Table.Where(t=>t.JiaoBanID ==jiaobanID && t.GoodsID ==GoodsID).FirstOrDefault();

    问题解决 页面响应不到100ms   同时调试中 生成的sql语句已经有 查询条件了

    问题出在  

    //查询
    public IQueryable<T> LoadEntities(Func<T, bool> wherelambda)
    {
      return db.Set<T>().Where<T>(wherelambda).AsQueryable();
    }

    为了验证,我在前台直接调用 

    return this.context.Set<tb_e_jiaoBanItem>().Where(t => t.JiaoBanID == jiaobanID && t.GoodsID == GoodsID).AsQueryable().FirstOrDefault();

    页面响应也是 100ms左右,性能没问题。直接调用 dbcontext的set<>方法 没问题。但跨了几层传递后 就有问题。并没有生成我想要的查询语句。

    这个问题原来别人也碰到过  http://www.cnblogs.com/yjmyzz/archive/2008/09/06/1285564.html

    如果传入Where的参数为Expression,则L2S会自动帮忙处理Expression的拼接;而如果传入的是Func,而L2S无法拼接Expression与Func,所以只好先把数据全部取出来,然后再应用Func来进行数据过滤。

    代码应该修改为:

    public virtual IEnumerable<T> LoadEntities(System.Linq.Expressions.Expression<Func<T,bool>> wherelambda)
    {
    return this.Table.Where<T>(wherelambda);
    }

  • 相关阅读:
    delegate和event的区别 (zz)
    delegate和event的区别 (zz)
    delegate和event的区别 (zz)
    delegate和event的区别 (zz)
    以太坊网络服务分析
    以太坊:P2P网络数据处理流程
    以太坊:P2P网络数据交互
    以太坊虚拟机的基本介绍
    Solidity概述及基本代码展示
    Solidity编译器和简单调试
  • 原文地址:https://www.cnblogs.com/wfy680/p/15409539.html
Copyright © 2020-2023  润新知