1

我有一个存储过程,它在 SQL Server Management Studio 中在大约 10 秒内生成 2,675 条记录。

但是,当我从 C# 应用程序调用它时,需要 1:05 才能填充DataTable. 我能做些什么来提高性能吗?

这是我填写的方式DataTable

public static DataTable GetDataTable(string procName, params SqlParameter[] procParams)
{
    using (_conn = new SqlConnection(_connStr))
    {
        SqlCommand cmd = _conn.CreateCommand();
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.CommandText = procName;

        if (procParams != null)
        {
            foreach (SqlParameter p in procParams)
            {
                cmd.Parameters.Add(p);
            }
        }

        _conn.Open();

        var da = new SqlDataAdapter(cmd);

        var table = new DataTable();
        da.Fill(table);

        return table;
    }
}

具体到这一步:

var table = new DataTable();
da.Fill(table);

几乎所有时间都被占用(几乎 60 秒)。

我以前使用这种方法处理过大数据,并且没有遇到这么多的延迟。

有什么建议或想法吗?

更新:

我们也尝试过DataReader这样的:

var dataReader = cmd.ExecuteReader();
table.Load(dataReader);
dataReader.Close();

更新:

在桌面报表查看器中为同一个报表运行相同的 sp 可以在 12 秒内获得结果。这是在 Web 和桌面上运行的同一份报告。为什么这么慢?

称为 SP:

这是为报告获取数据的 SP 运行。

ALTER PROCEDURE [dbo].[rptCheckRegDetail]
@ldStartDt as char(10) = '',
@ldEndDt as char(10) = '',
@lcStartCkNo as char(10)= ' ',
@lcEndCkNo as char(10) =' ',
@lcUniqSupNo as char(10)=' ',
@lcBk_Uniq as char(10)= ' ',
@lnStatus as int=1

as
begin
  declare @ChkHd table  (ApChk_uniq char(10),Bank char(35),Bk_acct_no char(15),
      iCheckno char(10),Checkno char(10),CheckDate smalldatetime,
      SupName char(35),CheckAmt numeric(12,2),Status char(15), Detail char(6),
      CheckNote text,ReconcileStatus char(1),ReconciledDate smalldatetime)

  Insert into @ChkHd        
    exec [CheckRegView] @ldStartDt,@ldEndDt,@lcStartCkNo,@lcEndCkNo,@lcUniqSupNo,@lcBk_Uniq,@lnStatus                       

  SELECT c1.ApChk_uniq, c1.Bank, c1.Bk_acct_no, c1.iCheckno, c1.Checkno, 
    c1.CheckDate, c1.SupName,
    case when 
        ROW_NUMBER() over (partition by c1.apchk_uniq order by c1.checkno) = 1 
      then CheckAmt else cast(0.00 as numeric(12,2)) end as CheckAmt,
    c1.status,c1.checknote,Apchkdet.item_no, Apchkdet.ponum, Apchkdet.invno,
    Apchkdet.invdate, Apchkdet.due_date, Apchkdet.item_desc, Apchkdet.invamount, 
    Apchkdet.disc_tkn, Apchkdet.aprpay,Apchkdet.apchk_uniq, Apchkdet.itemnote, 
    MICSSYS.LIC_NAME
      FROM      @ChkHd as C1 
        inner join apchkdet on apchkdet.APCHK_UNIQ = c1.ApChk_uniq
        cross join micssys
      ORDER BY  Checkno,Apchkdet.item_no
end
4

3 回答 3

1

SqlDataAdapter创建DataTable. _ 因为查询在 SSMS 中执行相对较快,所以可能DataTable是主要问题的人口。

如果您所做的只是读取数据并将其列出到其他地方,那么创建一个Dictionary<string, object>使用SqlDataReader.

您的方法可以替换为以下内容:

public static List<Dictionary<string, object>> GetDataTable(string procName, params SqlParameter[] procParams)
{
    using (_conn = new SqlConnection(_connStr))
    {
        using (SqlCommand cmd = _conn.CreateCommand())
        {
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.CommandText = procName;

            if (procParams != null)
            {
                foreach (SqlParameter p in procParams)
                {
                    cmd.Parameters.Add(p);
                }
            }

            _conn.Open();

            using (var reader = cmd.ExecuteReader())
            {
                var result = new List<Dictionary<string, object>>();

                while (reader.Read())
                {
                    var row = new Dictionary<string, object>();

                    for (int i = 0; i < reader.FieldCount; i++)
                    {
                       string fieldName = reader.GetName(i);
                       row.Add(fieldName, reader[fieldName]);
                    }

                    result.Add(row);
                }

                return result;
            }
        }
    }
}

我还没有测试过这段代码,但它应该几乎可以工作!:)

然后,您可以像这样遍历行:

foreach (var result in results)
{
    foreach (KeyValuePair<string, object> field in result)
    {
        string fieldName = field.Key;
        string fieldValue = field.Value.ToString(); // Cast to correct type here
    }
}
于 2013-05-23T14:16:05.053 回答
0

我有同样的问题,这就是我发现的。SQLDataAdapter 显然对 SmallDateTime 变量有问题。将 SmallDateTime 转换为正常的 DateTime,它应该会加速 DataReader。

因此,将 smalldatetime sql 转换如下:

Cast(@smalldatetimevar as datetime) smalldatetimevar

当我在我的项目中执行此操作时,table.Load(dataReader) 命令从超时变为立即返回结果集。

于 2013-10-31T19:54:32.523 回答
0

要查看是应用程序还是 SQL Server 运行缓慢,请使用SQL Profiler 跟踪执行的查询。

于 2013-10-31T20:24:36.527 回答