看到本文的标题,相信你会忍不住进来看看!

没错,本文要讲的就是这个重量级的东西,这个不仅仅支持单表查询,更能支持连接查询,

加入一个表10W数据,另一个表也是10万数据,当你用linq建立一个连接查询然后利用take,skip读取第N页数据的时候,

你的程序就挂了,因为,你很可能读取需要几十秒甚至几分钟以上。

下面来讲解一下,ASP.NET MVC + EF 利用存储过程读取大数据的详细过程。

1.首先,我们创建一个实体类PageinationInfo,主要用于分页,如下

  1. public class PageinationInfo
  2. {
  3. /// <summary>
  4. /// 要显示的表或多个表的连接
  5. /// </summary>
  6. public string strTable { get; set; }
  7.  
  8. /// <summary>
  9. /// 要查询的字段
  10. /// </summary>
  11. public string strField { get; set; }
  12.  
  13. /// <summary>
  14. /// 每页多少条记录
  15. /// </summary>
  16. public int pageSize { get; set; }
  17.  
  18. /// <summary>
  19. /// 当前页
  20. /// </summary>
  21. public int pageIndex { get; set; }
  22.  
  23. /// <summary>
  24. /// 查询条件,不需where
  25. /// </summary>
  26. public string strWhere { get; set; }
  27.  
  28. /// <summary>
  29. /// 用于排序的主键
  30. /// </summary>
  31. public string strSortKey { get; set; }
  32.  
  33. /// <summary>
  34. /// 用于排序,如:id desc (多个id desc,dt asc)
  35. /// </summary>
  36. public string strSortField { get; set; }
  37.  
  38. /// <summary>
  39. /// 排序,0-顺序,1-倒序
  40. /// </summary>
  41. public bool strOrderBy { get; set; }
  42.  
  43. /// <summary>
  44. /// 总记录数
  45. /// </summary>
  46. public int RecordCount { get; set; }
  47.  
  48. /// <summary>
  49. /// 总页数
  50. /// </summary>
  51. public int PageCount { get; set; }
  52.  
  53. /// <summary>
  54. /// 查询耗时,毫秒为单位
  55. /// </summary>
  56. public int UsedTime { get; set; }
  57.  
  58. }

2.然后我们再DAL层新建一个类 PageinationInfoService 主要用于实现分页读取数据,如下:

  1. public class PageinationInfoService
  2. {
  3. /// <summary>
  4. /// 获取分页列表
  5. /// </summary>
  6. /// <param name="pageinationInfo"></param>
  7. /// <returns></returns>
  8. public IList<Entity> GetPageinationInfoList<Entity>(PageinationInfo pageinationInfo) where Entity : class
  9. {
  10. dynamic result = null;
  11. using (SnsLearningLogManagerDB db = new SnsLearningLogManagerDB())
  12. {
  13. #region SqlParameter参数
  14. SqlParameter[] paras = new SqlParameter[];
  15. paras[] = new SqlParameter("strTable", DbType.String);
  16. paras[].Value = pageinationInfo.strTable;
  17.  
  18. paras[] = new SqlParameter("strField", DbType.String);
  19. paras[].Value = pageinationInfo.strField;
  20.  
  21. paras[] = new SqlParameter("pageSize", DbType.Int16);
  22. paras[].Value = pageinationInfo.pageSize;
  23.  
  24. paras[] = new SqlParameter("pageIndex", DbType.Int16);
  25. paras[].Value = pageinationInfo.pageIndex;
  26.  
  27. paras[] = new SqlParameter("strWhere", DbType.String);
  28. paras[].Value = pageinationInfo.strWhere;
  29.  
  30. paras[] = new SqlParameter("strSortKey", DbType.String);
  31. paras[].Value = pageinationInfo.strSortKey;
  32.  
  33. paras[] = new SqlParameter("strSortField", DbType.String);
  34. paras[].Value = pageinationInfo.strSortField;
  35.  
  36. paras[] = new SqlParameter("strOrderBy", DbType.Boolean);
  37. paras[].Value = pageinationInfo.strOrderBy;
  38.  
  39. paras[] = new SqlParameter("RecordCount", DbType.Int16);
  40. paras[].Value = pageinationInfo.RecordCount;
  41. paras[].Direction = ParameterDirection.Output;
  42.  
  43. paras[] = new SqlParameter("UsedTime", DbType.Int16);
  44. paras[].Value = pageinationInfo.UsedTime;
  45. paras[].Direction = ParameterDirection.Output;
  46. #endregion
  47.  
  48. try
  49. {
  50. result = db.Database.SqlQuery<Entity>("exec LYBPager @strTable,@strField,@pageSize,@pageIndex,@strWhere,@strSortKey,@strSortField,@strOrderBy,@RecordCount output,@UsedTime output", paras).ToList();
  51. pageinationInfo.RecordCount = (int)paras[].Value;
  52. pageinationInfo.UsedTime = (int)paras[].Value;
  53. }
  54. catch (Exception ex)
  55. {
  56. throw;
  57. }
  58. }
  59. return result;
  60. }
  61. }
  1. PageinationInfoService类中我们传入的参数是实体和PageinationInfo,实体主要是用于接收数据并封装到实体中,LYBPager 这个是数据库中存储过程的名称,而UsedTime 就是存储过程读取数据所用的时间
  2.  
  3. BLL层的东西,我就不贴出来了,你们或者用工厂模式或者用简单3层,这个都无关紧要。
  4.  
  5. 3.接下来,我们在Controller里来处理我们的业务需求,贴一段自己项目的代码作为分析,如下
  1. public ActionResult Index(string LabelName,string _Title,string _Content, int pageNumber = , int pageSize = )
  2. {
  3. #region 分页
  4. SnsModels.PageinationInfo pageinationInfo = new SnsModels.PageinationInfo();
  5. pageinationInfo.pageIndex = pageNumber;
  6. pageinationInfo.pageSize = pageSize;
  7. pageinationInfo.RecordCount = ;
  8. pageinationInfo.strField = "*";
  9. pageinationInfo.strOrderBy = true;
  10. pageinationInfo.strSortField = "ArticleID desc";
  11. pageinationInfo.strSortKey = "ArticleID";
  12. pageinationInfo.strTable = "ArticleInfo";
  13. pageinationInfo.strWhere = " 1=1";
  14. pageinationInfo.UsedTime = ;
  15. pageinationInfo.PageCount = ;
  16. #endregion
  17.  
  18. IList<SnsModels.LabelInfo> LabelInfoList = Repository.GetList<SnsModels.LabelInfo>();
  19. ViewBag.LabelInfoList = new SelectList(LabelInfoList,"LabelName","LabelName");
  20.  
  21. #region 参数处理
  22. if (LabelName != null)
  23. {
  24. if (!string.IsNullOrEmpty(LabelName))
  25. {
  26. pageinationInfo.strWhere += " and LabelName like '%" + HttpUtility.UrlDecode(LabelName.Trim()) + "%'";
  27. ViewBag.LabelInfoList = new SelectList(LabelInfoList, "LabelName", "LabelName",LabelName.Trim());
  28. }
  29. }
  30. if (_Title != null)
  31. {
  32. if (!string.IsNullOrEmpty(_Title))
  33. {
  34. pageinationInfo.strWhere += " and Title like '%" + _Title.Trim() + "%'";
  35. }
  36. }
  37. if (_Content != null)
  38. {
  39. if (!string.IsNullOrEmpty(_Content))
  40. {
  41. pageinationInfo.strWhere += " and Content like '%" + _Content.Trim() + "%'";
  42. }
  43. }
  44. #endregion
  45.  
  46. IList<SnsModels.ArticleInfo> List = PageinationInfoManager.GetPageinationInfoList<SnsModels.ArticleInfo>(pageinationInfo);
  47.  
  48. #region 传值
  49. ViewBag.List = List;
  50. ViewBag.pageNumber = pageNumber;
  51. ViewBag.pageSize = pageSize;
  52. ViewBag.RecordCount = pageinationInfo.RecordCount;
  53. ViewBag.LabelName =HttpUtility.UrlDecode(LabelName);
  54. ViewBag._Title = _Title;
  55. ViewBag._Content = _Content;
  56. #endregion
  57.  
  58. return View();
  59. }

上面我们通过把参数传递到PageinationInfo,然后根据传递的参数拼凑pageinationInfo.strWhere现实了多条件查询,

pageNumber,pageSize 我们已经传递到View,你可以通过Jquery插件展示你的分页,点击一下一页的时候,跳转回控制器就行了。

4,接下来,我给出存储过程,代码如下:

  1. USE [LearningLogManagerDB2]
  2. GO
  3. /****** Object: StoredProcedure [dbo].[LYBPager] Script Date: 07/30/2014 11:51:44 ******/
  4. SET ANSI_NULLS ON
  5. GO
  6. SET QUOTED_IDENTIFIER ON
  7. GO
  8.  
  9. --参数说明-------------------------------------------------------------
  10. /**//*
  11. @strTable --要显示的表或多个表的连接
  12. @strField --要查询出的字段列表,*表示全部字段
  13. @pageSize --每页显示的记录个数
  14. @pageIndex --要显示那一页的记录
  15. @strWhere --查询条件,不需where
  16. @strSortKey --用于排序的主键
  17. @strSortField --用于排序,如:id desc (多个id desc,dt asc)
  18. @strOrderBy --排序,0-顺序,1-倒序
  19. @RecordCount --查询到的总记录数
  20. @UsedTime --耗时测试时间差
  21. */
  22.  
  23. ALTER PROCEDURE [dbo].[LYBPager]
  24. @strTable varchar() = '[dbo].[ttable]',--表名
  25. @strField varchar() = '*', --查询字段
  26. @pageSize int = , --每页多少条记录
  27. @pageIndex int = , --当前页
  28. @strWhere varchar() = '1=1', --查询条件
  29. @strSortKey varchar() = 'id', --主键
  30. @strSortField varchar() = 'id DESC', --排序
  31. @strOrderBy bit = , --是否排序 1表示排序
  32. @RecordCount int OUTPUT, --总记录数
  33. @UsedTime int OUTPUT --查询耗时,毫秒为单位
  34. AS
  35. SET NOCOUNT ON
  36. Declare @sqlcount INT
  37. Declare @timediff DATETIME
  38. select @timediff=getdate()
  39. Begin Tran
  40. DECLARE @sql nvarchar(),@where1 varchar(),@where2 varchar()
  41. IF @strWhere is null or rtrim(@strWhere)=''
  42. BEGIN--没有查询条件
  43. SET @where1=' WHERE '
  44. SET @where2=' '
  45. END
  46. ELSE
  47. BEGIN--有查询条件
  48. SET @where1=' WHERE ('+@strWhere+') AND ' --本来有条件再加上此条件
  49. SET @where2=' WHERE ('+@strWhere+') ' --原本没有条件而加上此条件
  50. END
  51. --SET @sql='SELECT @intResult=COUNT(*) FROM '+@strTable+@where2
  52.  
  53. BEGIN
  54. SET @sql='SELECT @sqlcount=COUNT(*) FROM (select '+@strSortKey+' from '+ @strTable + @where2 +') As tmptab'
  55. END
  56. --print @sql
  57.  
  58. EXEC sp_executesql @sql,N'@sqlcount int OUTPUT',@sqlcount OUTPUT --计算总记录数
  59. SELECT @RecordCount = @sqlcount --设置总记录数
  60. IF @pageIndex= --第一页
  61. BEGIN
  62. SET @sql='SELECT TOP '+CAST(@pageSize AS varchar())+' '+@strField+' FROM '+@strTable+@where2+'ORDER BY '+ @strSortField
  63. END
  64. Else
  65. BEGIN
  66. IF @strOrderBy=
  67. SET @sql='SELECT TOP '+CAST(@pageSize AS varchar())+' '+@strField+ ' FROM '+
  68. @strTable+@where1+@strSortKey+'>(SELECT MAX('+case when charindex('.',@strSortKey)> then right(@strSortKey,len(@strSortKey)-charindex('.',@strSortKey)) else @strSortKey end+') '+ ' FROM (SELECT TOP '+
  69. CAST(@pageSize*(@pageIndex-) AS varchar())+' '+@strSortKey+' FROM '+@strTable+@where2+
  70. 'ORDER BY '+@strSortField+') t) ORDER BY '+@strSortField
  71. ELSE
  72. SET @sql='SELECT TOP '+CAST(@pageSize AS varchar())+' '+@strField+' FROM '+@strTable+@where1+
  73. @strSortKey+'<(SELECT MIN('+case when charindex('.',@strSortKey)> then right(@strSortKey,len(@strSortKey)-charindex('.',@strSortKey)) else @strSortKey end+') '+ ' FROM (SELECT TOP '+CAST(@pageSize*(@pageIndex-) AS varchar())+' '+
  74. @strSortKey+' FROM '+@strTable+@where2+'ORDER BY '+@strSortField+') t) ORDER BY '+@strSortField+''
  75. END
  76. print @sql
  77. --select @RecordCount
  78. EXEC(@sql)
  79. print @sql
  80. If @@Error <>
  81. Begin
  82. RollBack Tran
  83. Return -
  84. End
  85. Else
  86. Begin
  87. Commit TRAN
  88. set @UsedTime = datediff(ms,@timediff,getdate())
  89. --select @UsedTime
  90. --select datediff(ms,@timediff,getdate()) as 耗时
  91. Return @sqlcount
  92. End

当然存储过程不是本人写的,我只是利用而已,也用了很久了,感觉还可以,有兴趣的可以分析分析。

在此非常感谢很多博友加入本人ASP.NET MVC QQ群,并且都很踊跃提问。

本群提供ASP.NET MVC,EF,LINQ,WEB API技术支持,不在乎人多,在乎人精。
ASP.NET MVC群 171560784  
诚邀各路高手、初学者加入。

ASP.NET MVC + EF 利用存储过程读取大数据,1亿数据测试很OK的更多相关文章

  1. ASP.NET MVC + EF 利用存储过程读取大数据

    ASP.NET MVC + EF 利用存储过程读取大数据,1亿数据测试很OK 看到本文的标题,相信你会忍不住进来看看! 没错,本文要讲的就是这个重量级的东西,这个不仅仅支持单表查询,更能支持连接查询, ...

  2. ASP.NET MVC+EF框架+EasyUI实现权限管理系列(24)-权限组的设计和实现(附源码)(终结)

    ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇)   (1):框架搭建    (2):数据库访问层的设计Demo    (3):面向接口编程   (4 ):业务逻辑层的封装    ...

  3. ASP.NET MVC+EF框架+EasyUI实现权限管理系列

    http://www.cnblogs.com/hanyinglong/archive/2013/03/22/2976478.html ASP.NET MVC+EF框架+EasyUI实现权限管理系列之开 ...

  4. ASP.NET MVC+EF框架+EasyUI实现权限管理系列(11)-验证码实现和底层修改

    原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(11)-验证码实现和底层修改 ASP.NET MVC+EF框架+EasyUI实现权限管系列  (开篇)   (1):框架搭建    ...

  5. ASP.NET MVC+EF框架+EasyUI实现权限管理系列(9)-TT模板的学习

    原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(9)-TT模板的学习 ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇)   (1):框架搭建    (2): ...

  6. ASP.NET MVC+EF框架+EasyUI实现权限管理系列(1)-框架搭建

    原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(1)-框架搭建 ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇) 前言:这篇博客开始我们便一步一步的来实现这 ...

  7. ASP.NET MVC+EF框架+EasyUI实现权限管理系列之开篇

    原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列之开篇 前言:博客又有一段时间没有更新了,心里感觉这段时间空空的,好像什么都没有学下,所以就想写博客,所以就有了这个系列,这里当然也 ...

  8. ASP.NET MVC+EF框架+EasyUI实现权限管理系列(23)-设置角色遗留问题和为权限设置角色以及EasyUI Tabs的使用

    ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇)   (1):框架搭建    (2):数据库访问层的设计Demo    (3):面向接口编程   (4 ):业务逻辑层的封装    ...

  9. ASP.NET MVC+EF框架+EasyUI实现权限管理系列(21)-用户角色权限基本的实现说明

    原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(21)-用户角色权限基本的实现说明     ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇)   (1):框 ...

随机推荐

  1. LeetCode39 Combination Sum

    题目: Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C  ...

  2. flume监控之ganglia

    对于日志来说,我觉得监控意义不大,因为写的速度一般不会特别快,但是如果是spooldir source,里面一小时放入十几G的数据让flume解析,特别是在结合kafka或者其他框架的话,监控就显得重 ...

  3. 1.5.7 CharFilterFactories

    CharFilterFactories 字符过滤器是一个预处理输入字符的组件,字符过滤器可以链接如token过滤器,并放置在Tokenizer(分词器)的前面,字符过滤器可以添加,更改或删除字符,同时 ...

  4. 采用handle消息机制实现轮播效果

    // 自动轮播条显示 if (mhandle == null) { mhandle = new Handler() { public void handleMessage(Message mes) { ...

  5. 用bootstrapValidator来验证UEditor

    我们的项目使用了bootstrapValidator来作为前端校验,但是表单里面有一个UEditor,它用bootstrapValidator是没有效果的,为了页面风格统一,只好修修改改咯 首先来看一 ...

  6. 通用权限底层研究:Web应用限制IP访问的功能实现

    如果你的web应用受到恶意扫描或攻击,你会怎么处理呢?大多数时候从应用日志里可以看到恶意扫描或攻击,遇到此类情况,如有一个可以进行IP访问控制的功能就好些了. 现将在MVC下实现的一个IP访问限制功能 ...

  7. iOS之block块

    Block块. 1.声明Block int (^myBlock)(int n) = ^(int num) 类型 (^名称)(需要传的参数)= ^(参数) 2 __block 变量 在block块中修改 ...

  8. 从敏捷开发到小团队SVN

    一.敏捷之惑 敏捷开发,有一个很好的实践,“每天都可以产生一个可用于发布的版本”. 以前对这句话感到非常的困惑,因为我们手中的项目是残缺的,基本只是程序的一个功能片段,在未集成之前如何发布得了?当然这 ...

  9. date & dirname

    date 年:+%Y 月:+%m 日:+%d 时:+%H 或者 +%k 分:+%M 秒:+%S 周:+%w dirname 目录 获取目录的上级目录

  10. [wordpress] 输出一个过滤器绑定的方法

    参考了WordPress: How do I get all the registered functions for 'the_content' filter, function print_fil ...