从接口取出来的数据用Linq过滤后分页显示很慢,求高手帮助!

Refrain66 2016-05-17 01:42:51

下面是方法代码,每次页面加载都要很久,点翻页有时要反应10多秒才翻页,求高手指点问题出现在哪,从哪里着手,在此谢了


public ActionResult GetInvertUserList(string exstoreid, string exstoreuserid,string query, int? pageindex, int? pagesize,string sort)
{
string msg_crrltn_id = Unity.GetNumber();
GetInvestListRequest gilr = new GetInvestListRequest()
{
msg_txn_code = "100060",
msg_crrltn_id = msg_crrltn_id,
msg_flg = "0",
msg_sender = "1",
msg_time = Unity.getDate(DateTime.Now),
msg_sys_sn = msg_crrltn_id,
msg_ver = "0.1",
exstore_id = exstoreid,
exstore_user_id = exstoreuserid
};
string requestsignstr = UrlParam.GetParamStr(gilr);
requestsignstr = Server.UrlDecode(requestsignstr);
string requestsign = SignHelper.sign(requestsignstr, HA.PrivateKey);
string responsestr = HttpHelper.OpenReadWithHttps(HA.GetInvestList, requestsignstr + "&sign=" + requestsign, "utf-8");
GetInvestListResponse model = HttpHelper.parse<GetInvestListResponse>(responsestr);
if (!string.IsNullOrEmpty(query))
{
model.list = model.list.Where(o => o.user_id == query || o.realname == query).ToList();
}
if (!string.IsNullOrEmpty(sort)&&sort=="1")
{
model.list = model.list.OrderByDescending(o => o.invest_amount).ToList();
}
if (pageindex != null && pagesize != null)
{
return Json(new { list = model.list.Skip(pageindex.Value * pagesize.Value).Take(pagesize.Value).ToList(), an = model.list.Where(o => o.is_activity == "1").ToList().Count, iin = model.list.Where(o => o.invest_amount != decimal.Parse("0")).ToList().Count, count = model.list.Count }, JsonRequestBehavior.AllowGet);
}
else
{
return Json(new { list = model.list, an = model.list.Where(o => o.is_activity == "1").ToList().Count, iin = model.list.Where(o => o.invest_amount != decimal.Parse("0")).ToList().Count, count = model.list.Count }, JsonRequestBehavior.AllowGet);
}
}
...全文
260 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
Refrain66 2016-05-20
  • 打赏
  • 举报
回复
问题已经解决了,不是出在toList()上,当然可能现在数据几百条也提现不出来,但确实应该优化下。 问题出在 responsestr = HttpHelper.OpenReadWithHttps(HA.GetInvestList, requestsignstr + "&sign=" + requestsign, "utf-8"); 这里是用http协议去调用一个接口的数据,我用耗时调试每次都需要9秒左右. 我的解决方案是设置一个全局静态变量来接收从接口传来的数据(json格式),然后设置一个cookie作为标识,设置cookie过期时间,当cookie过期时则从新获取接口的数据,相当于缓存一样。于是问题就解决了。经测试目前还没有发现其它问题,如有不合理地方望大家给出建议。下面贴上改进后的方法。

  public ActionResult GetInvertUserList(string exstoreid, string exstoreuserid,string query, int? pageindex, int? pagesize,string sort)
        {
            string msg_crrltn_id = Unity.GetNumber();
            GetInvestListRequest gilr = new GetInvestListRequest()
            {
                msg_txn_code = "100060",
                msg_crrltn_id = msg_crrltn_id,
                msg_flg = "0",
                msg_sender = "1",
                msg_time = Unity.getDate(DateTime.Now),
                msg_sys_sn = msg_crrltn_id,
                msg_ver = "0.1",
                exstore_id = exstoreid,
                exstore_user_id = exstoreuserid
            };
            //如果全局变量jsonStr为空
            if (string.IsNullOrEmpty(jsonStr))
            {
                //调用方法从接口获取数据
                GetInvertUserInfo(gilr);
                //将当前用户ID传入全局变量
                ck_exstroe_id = exstoreid;
            }
            else //jsonStr不为空则判断
            {
                //如果当前用户ID和已经登录用户的ID不匹配
                if (ck_exstroe_id != exstoreid)
                {
                    //从接口获取新的数据
                    GetInvertUserInfo(gilr);
                    //将新登录的用户ID从新赋值给全局变量
                    ck_exstroe_id = exstoreid;
                }
                else //如果登录用户没有发生变化
                {
                    //判断第一次加载设置的cokie是否过期,过期cokie则为null,那么就从新从接口获取数据
                    if (string.IsNullOrEmpty(CookiesHelper.GetCookieValue("jscokie")) || CookiesHelper.GetCookie("jscokie") == null)
                    {
                        GetInvertUserInfo(gilr);
                    }
                }
            }  
            GetInvestListResponse model = HttpHelper.parse<GetInvestListResponse>(jsonStr);
            if (!string.IsNullOrEmpty(query))
            {
                model.list = model.list.Where(o => o.user_id == query || o.realname == query).ToList();
            }
            if (!string.IsNullOrEmpty(sort)&&sort=="1") 
            {
                model.list = model.list.OrderByDescending(o => o.invest_amount).ToList();
            }
            if (pageindex != null && pagesize != null)
            {
                return Json(new { list = model.list.Skip(pageindex.Value * pagesize.Value).Take(pagesize.Value).ToList(), an = model.list.Where(o => o.is_activity == "1").ToList().Count, iin = model.list.Where(o => o.invest_amount != decimal.Parse("0")).ToList().Count, count = model.list.Count }, JsonRequestBehavior.AllowGet);
            }
            else
            {
               return Json(new { list = model.list, an = model.list.Where(o => o.is_activity == "1").ToList().Count, iin = model.list.Where(o => o.invest_amount != decimal.Parse("0")).ToList().Count, count = model.list.Count }, JsonRequestBehavior.AllowGet);
            }
        }

 /// <summary>
        /// 调用接口数据,并且设置cokie
        /// </summary>
        /// <param name="gilr"></param>
        protected void GetInvertUserInfo(GetInvestListRequest gilr) 
        {
            string requestsignstr = "";
            string responsestr = "";
            requestsignstr = UrlParam.GetParamStr(gilr);
            requestsignstr = Server.UrlDecode(requestsignstr);
            string requestsign = SignHelper.sign(requestsignstr, HA.PrivateKey);
            responsestr = HttpHelper.OpenReadWithHttps(HA.GetInvestList, requestsignstr + "&sign=" + requestsign, "utf-8");
            //将已经获取的数据赋值给全局变量jsonStr
            jsonStr = responsestr;
            //移除过期的cokie
            CookiesHelper.RemoveCookie("jscokie");
            //添加一个新的cokie
            HttpCookie cookie = new HttpCookie("jscokie", "1");
            DateTime expires = default(DateTime);
            //设置cokie过期时间
            expires = DateTime.Now.AddMinutes(1);
            cookie.Expires = expires;
            //添加cokie对象里包含的键值,值为过期时间
            cookie.Values.Add("datett", expires.ToString());
            Response.Cookies.Add(cookie);
        }
Xanl 2016-05-18
  • 打赏
  • 举报
回复
使用Linq方式查询数据库归根结底还是生成SQl语句, 事实上ToList方法生成SQL语句,并且连接到数据库去查询, 你的代码里ToList太多了,每次都要查询一下数据库导致查询很慢 最好在处理前查询到所有需要的数据, an = model.list.Where(o => o.is_activity == "1").ToList().Count iin = model.list.Where(o => o.invest_amount != decimal.Parse("0")).ToList().Count 这两个分页数据(页码,单页显示数目)的ToList完全没必要。
圣殿骑士18 2016-05-18
  • 打赏
  • 举报
回复
tolist不是这么用的,一般最后一次tolist即可,除非查询非常复杂,你写不出一次性的linq
Hertz_liu 2016-05-18
  • 打赏
  • 举报
回复

model.list
    .Where(o => o.user_id == query || o.realname == query)  //检索条件
    .OrderByDescending(o => o.invest_amount)  //排序
    .Skip(10)  //跳过前10条数据
    .Take(10) //取第11-20条数据
    .ToList(); 
Refrain66 2016-05-17
  • 打赏
  • 举报
回复
引用 7 楼 sp1234 的回复:
#2 楼的真实的理论性含义是说,你应该用调试、测试的办法看看数据库端是仅仅一次输出一页数据到内存,还是输出了大量数据然后在内存里才进行分页。所谓“ToList 的毛病”就在于你把大量数据取到内存里、反序列之后,再分页。 所以强调“直接走的是 else 这个条件”,是没有理解 #2 楼的真正意思。不管你走的是 if 还是 else 部分,你的表达式都不是真正的 linq provider 的,而是 linq to object 的。而 linq to object 并不慢,但是要把一堆无用的数据花时间、卡死数据库系统,来反序列化到内存中,然后分页之后再丢弃,这就很慢了。
确实是一次性把数据都取出来后再分页..我现在还是菜鸟,虽然现在知道导致数据慢的原因,确不知道怎么下手,这段代码并不是我写的,我只是在原方法上加了个sort排序,还望跟您请教下解决思路,感激不尽...
  • 打赏
  • 举报
回复
比如说,数据库查询可能用100毫秒,在内存中分页可能用20毫秒,可是你把多余的数据反序列化到内存里则需要10~20秒钟。那么如果你能保证没有 toList 之类的代码这种代码(也就是保证 linq provider 能够编译出来一个直接从数据库系统上分页、而不是内存中再分页的代码),显然就能将 20秒的查询时间缩短到200毫秒了。
  • 打赏
  • 举报
回复
#2 楼的真实的理论性含义是说,你应该用调试、测试的办法看看数据库端是仅仅一次输出一页数据到内存,还是输出了大量数据然后在内存里才进行分页。所谓“ToList 的毛病”就在于你把大量数据取到内存里、反序列之后,再分页。 所以强调“直接走的是 else 这个条件”,是没有理解 #2 楼的真正意思。不管你走的是 if 还是 else 部分,你的表达式都不是真正的 linq provider 的,而是 linq to object 的。而 linq to object 并不慢,但是要把一堆无用的数据花时间、卡死数据库系统,来反序列化到内存中,然后分页之后再丢弃,这就很慢了。
Refrain66 2016-05-17
  • 打赏
  • 举报
回复
引用 3 楼 smilepasta035 的回复:
[quote=引用 2 楼 starfd 的回复:] if (!string.IsNullOrEmpty(query)) { model.list = model.list.Where(o => o.user_id == query || o.realname == query).ToList(); } if (!string.IsNullOrEmpty(sort)&&sort=="1") { model.list = model.list.OrderByDescending(o => o.invest_amount).ToList(); } 各种ToList充彻其中,是在想不出在这种数据全部被取出的情况下,怎么可能不慢…… 将这些ToList全部删除,然后在return的时候才ToList
去掉toList()的话会报错.... 错误 40 无法将类型“System.Collections.Generic.IEnumerable<Common.GetInvestListSub>”隐式转换为“System.Collections.Generic.List<Common.GetInvestListSub>”。存在一个显式转换(是否缺少强制转换?) [/quote] 页面第一次加载时就已经很慢了...直接走的是else这个条件
Whyni111 2016-05-17
  • 打赏
  • 举报
回复
没发现问题,,,
  • 打赏
  • 举报
回复
你不会加个临时变量么…… 非要用model.list来做为接收值?
Refrain66 2016-05-17
  • 打赏
  • 举报
回复
引用 2 楼 starfd 的回复:
if (!string.IsNullOrEmpty(query)) { model.list = model.list.Where(o => o.user_id == query || o.realname == query).ToList(); } if (!string.IsNullOrEmpty(sort)&&sort=="1") { model.list = model.list.OrderByDescending(o => o.invest_amount).ToList(); } 各种ToList充彻其中,是在想不出在这种数据全部被取出的情况下,怎么可能不慢…… 将这些ToList全部删除,然后在return的时候才ToList
去掉toList()的话会报错.... 错误 40 无法将类型“System.Collections.Generic.IEnumerable<Common.GetInvestListSub>”隐式转换为“System.Collections.Generic.List<Common.GetInvestListSub>”。存在一个显式转换(是否缺少强制转换?)
  • 打赏
  • 举报
回复
if (!string.IsNullOrEmpty(query)) { model.list = model.list.Where(o => o.user_id == query || o.realname == query).ToList(); } if (!string.IsNullOrEmpty(sort)&&sort=="1") { model.list = model.list.OrderByDescending(o => o.invest_amount).ToList(); } 各种ToList充彻其中,是在想不出在这种数据全部被取出的情况下,怎么可能不慢…… 将这些ToList全部删除,然后在return的时候才ToList
Refrain66 2016-05-17
  • 打赏
  • 举报
回复
目前显示取出来的数据量700多条
关于EF6的正式书籍很少,这个文章是国内翻译整理出来的,共46个小节。适合循序渐进的学习。 第1部分 开始使用实体框架之历史和框架简述 第2部分 开始使用实体框架之使用介绍 第3部分 实体数据建模基础之创建一个简单的模型 第4部分 实体数据建模基础之从已存在的数据库创建模型 第5部分 实体数据建模基础之有载荷和无载荷的多对多关系建模 第6部分 实体数据建模基础之使用Code First建模自引用关系 第7部分 实体数据建模基础之拆分实体到多表以及拆分表到多实体 第8部分 实体数据建模基础之继承关系映射TPT 第9部分 实体数据建模基础之继承关系映射TPH 第10部分 实体数据建模基础之两实体间Is-a和Has-a关系建模、嵌入值映射 第11部分 查询之异步查询 第12部分 查询之使用SQL语句 第13部分 查询之使用Entity SQL 第14部分 查询之查询中设置默认值和存储过程返回多结果集 第15部分 查询之与列表值比较和过滤关联实体 第16部分 查询之左连接和在TPH中通过派生类排序 第17部分 查询之分页过滤和使用DateTime中的日期部分分组 第18部分 查询之结果集扁平化和多属性分组 第19部分 查询之使用位操作和多属性连接(join) 第20部分 ASP.NET MVC中使用实体框架之在MVC中构建一个CRUD示例 第21部分 ASP.NET MVC中使用实体框架之在页面中创建查询和使用ASP.NET URL路由过虑 第22部分 加载实体和导航属性之延迟加载 第23部分 加载实体和导航属性之预先加载与Find()方法 第24部分 加载实体和导航属性之查询内存对象 第25部分 加载实体和导航属性之加载完整的对象图和派生类型上的导航属性 第26部分 加载实体和导航属性之延缓加载关联实体和在别的LINQ查询操作中使用Include()方法 第27部分 加载实体和导航属性之关联实体过滤、排序、执行聚合操作 第28部分 加载实体和导航属性之测试实体是否加载与显式加载关联实体 第29部分 加载实体和导航属性之过滤预先加载的实体集合和修改外键关联 第30部分 继承与建模高级应用之多对多关联 第31部分 继承与建模高级应用之自引用关联 第32部分 继承与建模高级应用之TPH与TPT (1) 第33部分 继承与建模高级应用之TPH与TPT (2) 第34部分 继承与建模高级应用之多条件与QueryView 第35部分 继承与建模高级应用之TPH继承映射中使用复合条件 第36部分 继承与建模高级应用之TPC继承映射 第37部分 继承与建模高级应用之独立关联与外键关联 第38部分 使用对象服务之动态创建连接字符串和从数据库读取模型 第39部分 使用对象服务之配置模型和使用单复数服务 第40部分 使用对象服务之从跟踪器中获取实体与从命令行生成模型(想解决EF第一次查询慢的,请阅读) 第41部分 使用对象服务之标识关系中使用依赖实体与异步查询保存 第42部分 POCO之使用POCO 第43部分 POCO之使用POCO加载实体 第44部分 POCO之POCO中使用值对象和对象变更通知 第45部分 POCO之获取原始对象与手工同步对象图和变化跟踪器 第46部分 POCO之领域对象测试和仓储测试

62,039

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧