首页 > 技术文章 > EntityFrameWork使用MySql数据库分页的BUG

Macbeth 2013-07-13 01:53 原文

环境

使用MySQL Connector NET 6.7.4+EF5.0+VS2010

问题描述

 

IQueryable<T>类型的Where方法和Skip或Take方法一起使用时,生成的SQL语句错误。

详细代码

首先定义一个Model

1 public class User
2 {
3     public string Id { set; get; }
4     public string Name { set; get; }
5 }

运行如下程序,本意是要查询User表中Name包含"Test"的记录,并返回前10条:

1 string Name = "Test";
2 var Data = db.Set<User>().Where<User>(o => o.Name.Contains(Name)).
3     OrderBy<User,string>(o=>o.Id).
4     Skip<User>(0).
5     Take<User>(10);

运行后抛出"执行命令定义时出错。有关详细信息,请参阅内部异常",调试发现生成的SQL如下:

1 SELECT
2 `Project1`.`Id`, 
3 `Project1`.`Name`
4 FROM `User` AS `Project1`
5  WHERE (LOCATE(@p__linq__0, `Extent1`.`Name`)) > 0
6  ORDER BY 
7 `Project1`.`Id` ASC LIMIT 0,10

原来生成的SQL中根本就没有 Extent1 这个别名,所以查询的时候自然就报错误,将代码修改成这样(即将变量直接换成文字):

1  var Data = db.Set<User>().Where<User>(o => o.Name.Contains("Test")).
2       OrderBy<User,string>(o=>o.Id).
3       Skip<User>(0).
4       Take<User>(10);

生成的SQL为:

1 SELECT
2 `Extent1`.`Id`, 
3 `Extent1`.`Name`
4 FROM `User` AS `Extent1`
5  WHERE `Extent1`.`Name` LIKE '%Test%'
6  ORDER BY 
7 `Extent1`.`Id` ASC LIMIT 0,10

运行结果正常。

之后将数据源换成SQL Server数据库后 同样的写法也一切正常,不知道这是不是MySql.Data.Entity生成SQL的一个BUG

 

解决办法

抱着试试的态度,将Where方法放到Take方法后即:

1 string Name = "Test";
2 var Data = db.Set<User>().OrderBy<User,string>(o=>o.Id).Skip<User>(0).Take<User>(10).Where<User>(o => o.Name.Contains(Name));

生成的SQL为:

 1 SELECT
 2 `Project1`.`Id`, 
 3 `Project1`.`Name`
 4 FROM (SELECT
 5 `Extent1`.`Id`, 
 6 `Extent1`.`Name`
 7 FROM `User` AS `Extent1`
 8  WHERE (LOCATE(@p__linq__0, `Extent1`.`Name`)) > 0
 9  ORDER BY 
10 `Extent1`.`Id` ASC LIMIT 0,10) AS `Project1`
11  ORDER BY 
12 `Project1`.`Id` ASC

Ok,运行,正常了。

推荐阅读