Linq-to-Sql Sproc - ToList()太慢了

时间:2013-05-01 23:37:46

标签: c# asp.net sql-server-2008 linq-to-sql stored-procedures

我正在使用Linq2Sql来返回存储过程的结果。 sproc在2秒内提供100,000条记录。应用ToList()需要2分钟。

该项目是一个ASP.NET WebForm。在代码隐藏中,我试图从事务系统中获取记录,以便为仪表板类型报告应用各种分析。 100K记录是平均月份的数据。使用较小的数据,一切正常。

using (FooDataContext dbml = new FooDataContext())
{
    var query = dbml.FooBar(OneParam, TwoParam, ThreeParam);
    //no delay

    var results = query.ToList();
    //takes over 2 minutes -- consistent network traffic throughout

    ReportGenerator.PivotTable(results);
    ReportGenerator.Chart(results);
    //etc.
}

我使用ToList()来利用Linq的水合sproc对象,这对于使用lambda表达式评估结果很方便。

但ToList()需要非常长的时间来构建这么多数据的每个结果。如果我在那段时间暂停这个过程,我可以看到它只是在sproc的构造函数中循环遍历。查看我的网络流量似乎确认代码将返回到每个对象的数据库。将DeferredLoadingEnabled设置为false没有帮助。

有趣的是,我认为存储过程的一个缺点是它们会立即将所有数据丢弃给您,而不是作为IQueryable?

3 个答案:

答案 0 :(得分:2)

我认为您正试图以不是最佳的方式解决问题。如果要提供仪表板报告,则应该有后台进程(可能是sql代理作业或Windows服务)构建物化仪表板表,其中的数字会缩小为较小的“报告dtos”,然后您可以查询并放入仪表板。我不关心SQL是什么,每个请求提取100k记录然后执行一些计算/处理以有意义的方式显示数据将会浪费并且执行速度较慢。

答案 1 :(得分:0)

在获取记录时尝试执行TOList()。这可能很快。 var query = dbml.FooBar(OneParam, TwoParam, ThreeParam).Tolist();并直接使用该集合,如

 ReportGenerator.PivotTable(query);
 ReportGenerator.Chart(query);

答案 2 :(得分:0)

我的解决方案是使用旧式ADO.NET来查询存储过程。显然不像L2S那么容易,但在这种情况下,与L2S一样快,它似乎为每一行运行程序。

public List<object> Foo(SqlConnection connection)
{
    var query = "[dbo].[FooBar]";
    var command = new SqlCommand(query, connection);
    command.CommandType = CommandType.StoredProcedure;
    connection.Open();

    var reader = command.ExecuteReader();
    var results = new List<object>(); // Or whatever type your data is.

    while (reader.Read())
    {
        // Make this work for your particular data structure:
        results.Add(reader.GetString(0));
    }

    connection.Close();

    return results;
}

另外,为了安全起见,请务必使用using语句创建连接:

using (var connection = new SqlConnection(connectionString))
{
    results = Foo(connection);
}

ReportGenerator.PivotTable(results);
ReportGenerator.Chart(results);
//etc.