c# - IQueryable<>.ToString() 太慢

标签 c# entity-framework linq-to-entities

我正在使用在这个问题的答案中找到的 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() 并且这将传递一个缓存版本。

相关帖子。 How do I cache an IQueryable object?

关于c# - IQueryable<>.ToString() 太慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13715613/

相关文章:

c# - 使用实体方法的结果通过 lambda 表达式或 linq 查询进行过滤

c# - 如何编写 linq 查询以防止重复连接?

c# - 防止多个线程/实例选择和处理 Azure SQL 数据库中的相同行

c# - 如何调用声明为抽象重写的基方法

c# - 在 C# 中使用 LINQ 从 localdb 获取数据时出现问题

c# - 如何在 Windows 8 Metro 风格应用程序中获取摄像头源?

asp.net - 使用 Entity Framework 和 VB.NET 构建解耦 N 层应用程序

c# - 在处理上下文后,如何从包含导航属性的 Entity Framework (数据库优先)返回模型?

entity-framework - Entity Framework : perform a query on a linking table/many to many relationship

c# - 如何从 C# 调用带有客户端证书的 Web 服务?