C# IQueryable<>;。ToString()太慢了
我使用的是BatchDelete,可以在这个问题的答案上找到: 该方法似乎浪费了太多时间从IQueryable构建delete子句。具体来说,使用下面的IQueryable删除20000个元素几乎需要两分钟C# IQueryable<>;。ToString()太慢了,c#,entity-framework,linq-to-entities,C#,Entity Framework,Linq To Entities,我使用的是BatchDelete,可以在这个问题的答案上找到: 该方法似乎浪费了太多时间从IQueryable构建delete子句。具体来说,使用下面的IQueryable删除20000个元素几乎需要两分钟 context.DeleteBatch(context.SomeTable.Where(x => idList.Contains(x.Id))); 所有时间都花在这条线上: var sql = clause.ToString(); 该行是此方法的一部分,可在上面链接的原始问
context.DeleteBatch(context.SomeTable.Where(x => idList.Contains(x.Id)));
所有时间都花在这条线上:
var sql = clause.ToString();
该行是此方法的一部分,可在上面链接的原始问题上使用,但粘贴在此处是为了方便:
private static string GetClause<T>(DbContext context, IQueryable<T> clause) where T : class
{
const string Snippet = "FROM [dbo].[";
var sql = clause.ToString();
var sqlFirstPart = sql.Substring(sql.IndexOf(Snippet, System.StringComparison.OrdinalIgnoreCase));
sqlFirstPart = sqlFirstPart.Replace("AS [Extent1]", string.Empty);
sqlFirstPart = sqlFirstPart.Replace("[Extent1].", string.Empty);
return sqlFirstPart;
}
private静态字符串GetClause(DbContext上下文,IQueryable子句),其中T:class
{
const string Snippet=“FROM[dbo].[”;
var sql=子句.ToString();
var sqlFirstPart=sql.Substring(sql.IndexOf(Snippet,System.StringComparison.OrdinalIgnoreCase));
sqlFirstPart=sqlFirstPart.Replace(“AS[Extent1]”,string.Empty);
sqlFirstPart=sqlFirstPart.Replace(“[Extent1]”,string.Empty);
返回第一部分;
}
我想象将context.SomeTable.Where(x=>idList.Contains(x.Id))
放入一个已编译的查询中可能会有所帮助,但如果在EF 5上使用DbContext,您就不能编译查询。在论文中,它们应该被缓存,但我认为在第二次执行相同的BatchDelete时没有任何改进的迹象
有什么方法可以加快速度吗?我希望避免手动生成SQL delete语句。IQueryable没有缓存,每次计算它时,您都要使用SQL。对其运行ToList()或ToArray()将对其进行一次计算,然后您可以将该列表作为缓存版本使用 如果要保留自己的接口,可以使用ToList().AsQueryable(),这将传入一个缓存版本 相关职位。
在这种情况下,似乎没有办法缓存IQueryable,因为查询包含要检查的ID列表,并且列表在每次调用中都会更改 我发现避免每次必须批量删除对象时生成查询时出现两分钟延迟的唯一方法是使用ExecuteSqlCommand,如下所示:
var list = string.Join("','", ids.Select(x => x.ToString()));
var qry = string.Format("DELETE FROM SomeTable WHERE Id IN ('{0}')", list);
context.Database.ExecuteSqlCommand(qry);
我现在将此标记为答案。如果建议使用任何其他不依赖ExecuteSqlCommand的技术,我将很乐意更改答案。有一种EF模式可以正常工作 它使用投影。仅从DB返回键。(投影不会添加到上下文, 所以这很快。 然后,使用仅密钥存根POCO构建上下文,并点亮保险丝 基本上
var deleteMagazine = Context.Set<DeadMeat>.Where(t=>t.IhateYou == true).Select(t=>t.THEKEY).toList
//Now instantiate a dummy POCO with KEY only for the list,
foreach ( var bullet in deleteMagazine)
{
context.Set<deadmeat>.attach(bullet);
context.set<deadmeat>.remove(bullet);
// consider saving chnages every 1000 records .... performance, trial different values
if (magazineisEmpty) // your counter logic here :-)
context.SaveChanges
}
// shoot anyone still moving
context.SaveChanges
var deleteMagazine=Context.Set.Where(t=>t.IhateYou==true)。选择(t=>t.THEKEY)。toList
//现在仅为列表实例化一个具有密钥的伪POCO,
foreach(删除库中的var项目符号)
{
context.Set.attach(项目符号);
context.set.remove(项目符号);
/考虑每隔1000个记录保存一次。
if(magazineisEmpty)//此处的计数器逻辑:-)
context.SaveChanges
}
//射杀任何仍在移动的人
context.SaveChanges
检查SQL server profiler…ToList().AsQueryable()是否只缓存该特定元素集的子句解析?如果是这样,将没有多大帮助。