我在ado.net实体框架中的实体中遇到了一些问题。基本上我正在做的是:
var results = (from c in companies
where c.Name.StartsWith(letter)
select c);
并将其转换为SQL,如:
WHERE (CAST(CHARINDEX(@p, [Extent1].[Name]) AS int)) = 1
这很好,但我的表有数百万条记录,所以运行速度非常慢。我需要它生成的是:
WHERE Name LIKE @p + '%'
我搜索高低,除了使用存储过程或使用实体sql之外无法找到任何解决方案......
有没有办法通过linq做到这一点?可能通过某种方式将linq扩展到实体linq提供程序,或以某种方式拦截命令树或生成的查询?
答案 0 :(得分:3)
我不是SQL专家,但猜测两种语法:
WHERE(CAST(CHARINDEX(@ p,[Extent1]。[Name])AS int))= 1
和
名称如@p +'%'
将导致表扫描或理想情况下的索引扫描。底线他们将执行相同的操作。我通过查看下面的执行计划来验证这一点。最重要的是,您需要重新考虑数据库架构或执行搜索的方式。这不是LINQ问题。
一个可能的改进领域:确保您已将要搜索的列编入索引。
答案 1 :(得分:2)
LIKE @p0 + '%'
...非常奇怪。
您使用的是哪个EF提供商(数据库)? SQL Server?
正如你所说,存储过程将完成这项工作,但你不应该 这样做......非常非常奇怪......
答案 2 :(得分:1)
这是Linq to Entities的known issue。与LIKE不同,显然这个构造不使用索引。
我们使用Substring(转换为SUBSTRING)取得了一些成功。执行计划类似,但在我们的例子中,查询执行得更快。
这是另一个“我确定它将在EF 2中修复”......: - (
答案 3 :(得分:0)
“letter”是char吗?如果你把它变成了一个字符串,会发生什么?
var results = (from c in companies
where c.Name.StartsWith(letter.ToString())
select c);
答案 4 :(得分:0)
我尝试使用此语法
Name.Substring(0, 1) == "E"
生成此SQL
WHERE N'E' = (SUBSTRING([Name], 0 + 1, 1))
也许这更有效率?
答案 5 :(得分:0)
您可以非常轻松地使用链接到实体中的真实
以下是使其运作所需的条件:
添加
<Function Name="String_Like" ReturnType="Edm.Boolean">
<Parameter Name="searchingIn" Type="Edm.String" />
<Parameter Name="lookingFor" Type="Edm.String" />
<DefiningExpression>
searchingIn LIKE lookingFor
</DefiningExpression>
</Function>
到此标签中的EDMX:
EDMX:EDMX / EDMX:运行/ EDMX:ConceptualModels /模式
还要记住<schema namespace="" />
属性
然后在上面的命名空间中添加一个扩展类:
public static class Extensions
{
[EdmFunction("DocTrails3.Net.Database.Models", "String_Like")]
public static Boolean Like(this String searchingIn, String lookingFor)
{
throw new Exception("Not implemented");
}
}
此扩展方法现在将映射到EDMX功能。
此处有更多信息:http://jendaperl.blogspot.be/2011/02/like-in-linq-to-entities.html