我正在使用在这个问题的答案中找到的 BatchDelete:EF Code First Delete Batch From IQueryable<T>?
该方法似乎浪费了太多时间从 IQueryable 构建删除子句。具体来说,使用下面的 IQueryable 删除 20.000 个元素需要将近两分钟。
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;
}
我想象将 context.SomeTable.Where(x => idList.Contains(x.Id))
制作成编译查询可能会有所帮助,但据我所知,您无法在使用 DbContext 时编译查询EF 5。在论文中,它们应该被缓存,但我没有看到第二次执行同一个 BatchDelete 有任何改进的迹象。
有没有办法让它更快?我想避免手动构建 SQL 删除语句。
最佳答案
IQueryable 没有被缓存,每次你对它求值时你都会使用 SQL。在其上运行 ToList() 或 ToArray() 将对其求值一次,然后您可以使用该列表作为缓存版本。
如果你想保留你的接口(interface),你可以使用 ToList().AsQueryable() 并且这将传递一个缓存版本。
关于c# - IQueryable<>.ToString() 太慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13715613/