您的位置:首页 > 数据库

Linq to Sql 或linq to entities 与SQL查询结果不一致 返回重复结果问题

2015-12-17 17:16 561 查看
用Entity Framework开发项目过程中,发现linq查询返回的结果,与SQL查询出的结果不一致。

问题表现为:SQL返回了我们期望的结果,但是LINQ查询出来的结果确是一些重复记录。

这种问题一般是对数据库视图进行查询时发生,问题产生的原因及现象如下:

1)使用.net 的linq to sql,或linq to entities 生成的实体对象,出于为提高效率等原因,会对每个对象自动判断出一些列做为实体对象的Key(EntityKey),

这个Key就是相当于我们表中的主键,查询结果时,会根据这个Key列的值进行判断,假设数据库中有视图View1有3条记录如下:

====View1=====

列1(key列) 列2 列3

1 a1 a1

1 a2 a2

3 a3 a3

2)假设此View1的实体对象中,列1判断为Key列(标识列),如果当前我们有一个如下的查询,SQL语句如下:

SELECT 列1,列2,列3 FROM [View1]

显然,查询出来正确的结果为:

====SQL返回正确的结果=====

列1(key列) 列2 列3

1 a1 a1

1 a2 a2

3 a3 a3

3)但是如果你用LINQ语句去查:var objs = db.entity.select(v=>v);//entity为实体对象

得出的结果为:

====LINQ返回错误的结果=====

列1(key列) 列2 列3

1 a1 a1

1 a1 a1 (这行是错误的)

3 a3 a3

问题分析:

我们会发现,第2条记录与第一条记录是一样的,原因就在于实体对象中的Key列即列1的值相同(在我们的例子中都为1),

那么LINQ返回第一条数据时,没有问题,正常返回;

返回第二条时,判断Key列的值,发现都为1,那么就认为第二条数和第一条数据是一样的,所以直接返回第一行记录的值,做为第二条记录。

第三条记录,key列不同,取回正确数据。

如果LINQ的查询还附加排序也会影响LINQ查询的结果,总之会返回不同的错误结果

解决方法:

1.找出视图中可以用来唯一标识该行记录的那些列,在edmx中将它们设为实体键(Key列),在我的项目中还给这个字段加了唯一键约束,防止[b]LINQ查询结果出错。[/b]

通过上面分析,我们就可以明白为什么出现这种问题都是在使用视图的时候,因为如果是表的话,那么基本上主键会被判断为实体对象的Key,显示不会出现数据重复问题。

但是视图就不一样,特别是一些GroupBy语句创建的视图,.net底层自动判定的EntityKey,就会有问题,一般都是随便找一个或者几个列,GroupBy 语句的视图中,

基本上没有哪一个或者哪几个字段能做为记录唯一标识,那么我们只能给记录生成标识列来解决。

比如有一个视图View2的创建语句如下:

select col1,col2,col3,count(col4) as col4 from group by col1,col2,col3

此时为了避免错误的结果,有些朋友,就把视图中col1,col2,col3的列都设为实体键,这样的确可以避免一些问题,有时候列太多了,全设为实体键,不是一个好办法。

但是,我们可以给记录自动生成列,就是使用 row_number() 方法,比如可以使用如下语句创建视图:

select [index]=row_number() over (order by ID), col1,col2,col3,count(col4) as col4 from
group by col1,col2,col3

然后将index列设为实体键就OK了。

2.使用EF执行SQL语句的方法 DbContext.Database.SqlQuery<T>(视图名),也可以解决问题,效率就不用我说,通过SQL Server Profiler跟踪测试一下就知道了。

本文参考了TobeorNot的经验加补充,如有更好的方法,请指教。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: