【发布时间】:2013-09-27 06:52:50
【问题描述】:
我正在使用 VS2008、.NET 3,5、Entity Framework 3.5、Sql Server Compact 3.5 SP2。 SQL SC 3.5 使用 EF 访问,采用数据库优先方法。
我正在使用一个简单的查询(linq 和 EF),它应该对列 StanjeId (tinyint) 和 ArtiklId (int) 使用现有的复合索引。
var compQuery2 = from art in MobileDb.Artikl
where art.Stanje.StanjeId == (byte)1
&& art.ArtiklId == tmp1
select art;
var quer1 = MobileDb.Artikl.Where(a => a.Stanje.StanjeId == (byte)1 && a.ArtiklId == tmp1);
使用(compQuery2 as System.Data.Objects.ObjectQuery).ToTraceString()生成的查询是:
SELECT
1 AS [C1],
[Extent1].[ArtiklGuid] AS [ArtiklGuid],
.
.
[Extent1].[StanjeId] AS [StanjeId],
[Extent1].[ZemljaPorijeklaDrzavaGuid] AS [ZemljaPorijeklaDrzavaGuid]
FROM [Artikl] AS [Extent1]
WHERE (1 = ( CAST( [Extent1].[StanjeId] AS int))) AND ([Extent1].[ArtiklId] = @p__linq__4)
问题是生成的查询在查询的 where 列 StanjeId 的 where 部分使用强制转换为 int,尽管 StanjeId 的类型是 tinyint(字节等效)。这导致 SQL SC 3.5 不使用索引查找,而是使用非常慢的表扫描(表有 >1M 记录)。
如何让 EF 3.5 在生成的 SQL 查询的 where 部分不使用 CAST as int?
【问题讨论】:
-
你用了什么
byte变量分配给1,byte one=1而不是(byte)1? -
WHERE 部分生成的查询现在是:WHERE (( CAST( [Extent1].[StanjeId] AS int)) = ( CAST( @p__linq__3 AS int))) AND ([Extent1]. [ArtiklId] = @p__linq__4) 所以通常是一样的,但现在 StanjeId 列和变量一都被分别转换为 int。
-
试试这个操作符
Byte.CompareTo(Byte),art.Stanje.StanjeId.CompareTo(one) == 0,即使这显式转换,我们也必须开始寻找差异方法的源代码/ -
感谢 Rameez :) 您的解决方案效果很好,并从生成的 SQL 查询中删除了 CAST。为什么 art.Stanje.StanjeId == (byte)1 生成的代码与 art.Stanje.StanjeId.CompareTo(one) == 0 不同,尽管逻辑上应该相同?
-
在下面发布了答案,因为它可能对其他人有所帮助,从逻辑上讲,C# 中的许多东西看起来都是一样的,但是当我们查看源代码或 ILDASM 时,我们会意识到不同之处。但是你的问题比我的回答重要得多:)谢谢
标签: c# .net entity-framework sql-server-ce-3.5