C# LINQ需要40秒才能结束查询-性能
我正在呼叫本地网络之外的外部数据库,但是查询需要40秒才能结束 我正在用edmx打电话C# LINQ需要40秒才能结束查询-性能,c#,performance,linq,ef-code-first,edmx,C#,Performance,Linq,Ef Code First,Edmx,我正在呼叫本地网络之外的外部数据库,但是查询需要40秒才能结束 我正在用edmx打电话 String Example = "Example"; var Result = EDMXEntity.Entities .Where( x => ( x.Name.ToString().ToLower().Contains(Example.ToLower()) )) .Take(50) .ToList()
String Example = "Example";
var Result = EDMXEntity.Entities
.Where(
x =>
(
x.Name.ToString().ToLower().Contains(Example.ToLower())
))
.Take(50)
.ToList();
当前代码感谢Szer:
var Result = EDMXEntity.Entities.Where(x => SqlFunctions.PatIndex(x.Name.ToString().ToLower(), Example.ToLower()) > 0).Take(50).ToList();
SQLServerManagementStudio在不到一秒钟的时间内完成了这项工作
很可能这是由错误的缓存查询执行计划造成的,如前所述,以及
人们发现,对SQL Server运行以下命令可以解决这个问题。(可能只需要第二个命令。)
字符串比较的最佳选择是使用用例不等式,这样就不必处理字符串转换问题。在这种情况下,名称上的.ToString并不是必须的,我想也不是(同样,我也不确定它是如何存储的,所以可能需要它)。此外,对于名称,您可以尝试使用相等或至少相等 最后,您可以尝试将其拆分为一个可查询的对象,并以这种方式运行查询。通过这种方式,您可以减少用于查询本身的资源数量 编辑 因为不希望检查整个字符串,所以可以使用IndexOf来代替,以避免使用完整的字符串 见下文:
String Example = "Example";
var EDMXEntity = new List<String>();
var Query = EDMXEntity.Entities.AsQueryable();
var Result = Query
.Where(
x =>
(
x.Name.ToString().ToLower().Contains(Example.ToLower())
))
.Take(50)
.ToList();
String-Example=“Example”;
var EDMXEntity=新列表();
var Query=EDMXEntity.Entities.AsQueryable();
var结果=查询
.在哪里(
x=>
(
x、 Name.ToString().ToLower().Contains(例如.ToLower())
))
.Take(50)
.ToList();
以上我的评论的迟交回复:
问题是您正在将所有实体从数据库加载到内存,并在计算机上进行筛选。在使用数据库引擎之前,您应该过滤查询
为此,您应该使用LINQSQL提供程序映射到直接T-SQL代码的。
在本例中,您可以将string.Contains()
替换为SqlFunctions.PatIndex
,这几乎是相同的(它返回int
而不是bool
)
像这样:
var result = EDMXEntity.Entities
.Where(x => SqlFunctions.PatIndex(
stringPattern: x.Name.ToString().ToLower(),
target: Example.ToLower()) > 0)
.Take(50)
.ToList();
您的
IQueryable
转换为从[Extent1]中选择前50个*,其中(CAST(CHARINDEX(LOWER(@p\u linq\u 0),LOWER(当([Extent1].[Name]为NULL时为小写),然后N''ELSE[Extent1].[Name]END]作为INT))>0
。可能where子句是您提出的关于如何提高性能的问题的原因?@Lightwalker请尝试以下方法:var Result=EDMXEntity.Entities.where(x=>SqlFunctions.PatIndex(x.Name.ToString().ToLower(),Example.ToLower())>0)代码>@Szer这是我的第一个猜测,但sql server management studio在不到一秒钟的时间内就做到了。@Lightwalker doneDylan,这种方法的问题是,查询需要完整的字符串,这意味着如果用户的名字是“Joh”,如果搜索“Joh”,则不会得到任何数据,这就是为什么(感谢@Szer)我使用了SqlFunctions.PatIndex(“%”+Example.ToLower()+“%”,x.Name.ToString().ToLower())>0,但由于只有在执行.ToList()时才运行查询,因此可能会更快。@Lightwalker我已使用更好的实现(不只是使用完整字符串)更新了代码。linq抛出错误。。。“LINQ to Entities无法识别方法‘Int32 IndexOf(System.String,System.StringComparison)’方法,此方法无法转换为存储表达式。”编辑代码和初始代码之间的唯一区别是.AsQueryable();
var result = EDMXEntity.Entities
.Where(x => SqlFunctions.PatIndex(
stringPattern: x.Name.ToString().ToLower(),
target: Example.ToLower()) > 0)
.Take(50)
.ToList();