我正在使用 EF 4.4.20627.0
和 MySQL 5.6
,MySQL .net 连接器
版本 6.6.4
我有一个这样的方法,它生成的 sql 非常非常慢
(需要超过 1 分钟)
private List<TNews> GetPagedNews(int pagenum, int pagesize,
AdvSearcherArgs advcArgs, string keyword)
{
var dataSrc = _dbRawDataContext.TNews.Where(x => x.Id>0);
if (!string.IsNullOrWhiteSpace(advcArgs.PMAC))
{
dataSrc = dataSrc.Where(m => m.Pmac == advcArgs.PMAC);
}
if (!string.IsNullOrWhiteSpace(advcArgs.BegineDate))
{
var begin = Convertion.ToDate(advcArgs.BegineDate);
var end = Convertion.ToDate(advcArgs.EndDate);
dataSrc = dataSrc.Where(m => m.PmacDT >=begin && m.PmacDT<end);
}
dataSrc = dataSrc.OrderByDescending(n => n.PmacDT).Skip(pagenum * pagesize).
Take(pagesize);
var cnt = dataSrc.Count();
SetPagerValues(pagenum, pagesize, cnt);
return dataSrc.ToList();
}
生成的sql是这样的:
SELECT
`Project1`.*
FROM
(
SELECT
`Extent1`.*
FROM `tnews` AS `Extent1`
WHERE (`Extent1`.`Id` > 0)
AND ((`Extent1`.`PmacDT` >= '2013-01-01 00:00:00 ') AND
(`Extent1`.`PmacDT` < '2013-01-07 00:00:00 '))
) AS `Project1`
ORDER BY
`Project1`.`PmacDT` DESC LIMIT 0,20
/* Affected rows: 0 Found rows: 20 Warnings: 0 Duration for 1 query: 00:01:30 */
如果我将 order by
和 limit
子句移动到大括号中,此 sql 将非常快
(成本低于 1秒
):
SELECT
`Project1`.*
FROM
(
SELECT
`Extent1`.*
FROM `tnews` AS `Extent1`
WHERE (`Extent1`.`Id` > 0)
AND ((`Extent1`.`PmacDT` >= '2013-01-01 00:00:00 ') AND
(`Extent1`.`PmacDT` < '2013-01-07 00:00:00 '))
ORDER BY
`PmacDT` DESC LIMIT 0,20
) AS `Project1`
/* Affected rows: 0 Found rows: 20 Warnings: 0 Duration for 1 query: 0.000 sec. */
ProjectX
和 Extent1
是什么意思?
以及为什么 Entity Framework 不将 orderby * limit x,y
放在实际查询之外??
sql 很奇怪,肯定会使查询非常慢,我永远不会那样写 sql...那么如何让 EF 生成一个CORRECT
sql??
有什么建议吗?
最佳答案
只是一个快速的猜测:Count() 和 ToList() 都执行查询。首先执行 ToList(),然后使用接收到的列表获取元素的数量。
像这样:
private List<TNews> GetPagedNews(int pagenum, int pagesize,
AdvSearcherArgs advcArgs, string keyword)
{
var dataSrc = _dbRawDataContext.TNews.Where(x => x.Id>0);
if (!string.IsNullOrWhiteSpace(advcArgs.PMAC))
{
dataSrc = dataSrc.Where(m => m.Pmac == advcArgs.PMAC);
}
if (!string.IsNullOrWhiteSpace(advcArgs.BegineDate))
{
var begin = Convertion.ToDate(advcArgs.BegineDate);
var end = Convertion.ToDate(advcArgs.EndDate);
dataSrc = dataSrc.Where(m => m.PmacDT >=begin && m.PmacDT<end);
}
dataSrc = dataSrc.OrderByDescending(n => n.PmacDT).Skip(pagenum * pagesize).
Take(pagesize);
var myList = dataSrc.ToList(); //execute the query to an in-memory list
var cnt = myList.Count(); //get the count from the already exeuted query
SetPagerValues(pagenum, pagesize, cnt);
return myList; //return the list
}
关于c# - linq 到实体 : linq query performance optimization,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14191998/