从ASP.NET

时间:2018-04-18 18:53:43

标签: c# datatable sqlcommand

我遇到了存储过程的问题我尝试从ASP.NET控制台应用程序运行。

这就是我试图在代码中获得结果的方式:

public static DataTable PerformStoredProcedure(int PracticeID, string CommandName)
    {

        DataTable dt = new DataTable();

        try
        {
            using (SqlConnection conn = new SqlConnection(System.Configuration.ConfigurationManager.AppSettings["DbConnString"].ToString()))
            {
                conn.Open();

                using (SqlCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.CommandText = CommandName;
                    cmd.Parameters.AddWithValue("@practiceID", PracticeID);

                    using (SqlDataAdapter da = new SqlDataAdapter(cmd))
                    {
                        da.Fill(dt);
                    }
                }

                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    for (int j = 0; j < dt.Rows[i].ItemArray.Length; j++)
                    {
                        Console.Write(dt.Rows[i].ItemArray[j] + ",");
                    }
                    Console.WriteLine();
                }
            }
        }

运行程序后,我返回一个没有错误的空白数据集。但是,当我在SQL Server Management Studio中运行该过程时,我的工作正常。

您可能会注意到在启动new SqlCommand()时我没有使用SqlCommand cmd构造函数。这是因为查询非常庞大,需要一段时间才能运行,因此我认为这是一个超时问题。

根据建议here,我创建了以下类以调整执行超时限制。

class CommandFactory
{
            public static int CommandTimeout
            {
                get
                {
                    int commandTimeout = 0;
                    var configValue = ConfigurationManager.AppSettings["commandTimeout"];

                    if (int.TryParse(configValue, out commandTimeout))
                        return commandTimeout;

                    return 120;
                }
            }

我想包括这一点,以避免混淆SqlCommand是否正确初始化。在调整之后,我开始遇到命令返回空白数据表的问题。我认为这可能与数据表dt的最小容量有关,因此我在原始代码中进行了调整。

我已经做了额外的研究,并提出了建议无效的建议修补程序:

1.

上设置nocount

2.使用数据适配器而不是数据读取器

3.这是最详细的答案。在论坛中提出了一些建议,但最终解决方案与数据库默认使用的视图和阻止访问所需数据有关。我已经与DBA确认我们不会这样做。

就像我之前提到的那样,存储过程中包含的查询是巨大的,我还没有把它包含在这里,因为它的大小很大,因为这个帖子足够长。我再次确认该程序在SSMS中有效。

我还没有包含示例结果集,因为数据包含受限制的信息。

感谢您提供的任何帮助。

更新:

我添加了另一个调用存储过程的方法,以查看问题是否特定于被调用的特定过程。第二个存储过程也返回了一个空白数据表,因此问题不是特定于任何一个过程。 (我还确认第二个程序正在工作并在SSMS中返回行)

这让我相信该项目的app.config文件有问题。然后我添加了第三个方法,在解决方案中的另一个项目上调用存储过程。但是,即使返回了空白数据表。

想象一下,当我发现它们时,我会提供线索。

1 个答案:

答案 0 :(得分:1)

你很亲密。以下是一些指示:

  1. 永远不会打开SqlConnection。您需要按顺序拨打.Open() 建立连接。
  2. 如果你设定 .Fill()行上的断点并将鼠标悬停在DataTable上 对象,它看起来好像DataTable为空(如您所见),但.Fill()实际填充了Rows DataTable为您 自动(见MSDN)。我敢打赌,如果你循环通过Rows,你会发现 您的查询实际上一直在返回数据。
  3. 您可以使用using语句自动为您调用.Dispose()并关闭SqlConnection
  4. 以下是您的方法的更新版本:

    public static DataTable getAllModifiedChargesToday(int practiceID)
    {
        DataTable dt = new DataTable();
    
        try
        {
            using (SqlConnection conn = new SqlConnection(System.Configuration.ConfigurationManager.AppSettings["DbConnString"].ToString()))
            {
                conn.Open();
    
                using (SqlCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.CommandText = "ch_getAllModifiedChargesToday";
                    cmd.Parameters.AddWithValue("@practiceID", practiceID);
    
                    using (SqlDataAdapter da = new SqlDataAdapter(cmd))
                    {
                        da.Fill(dt);
                    }
                }
            }
        }
        catch (Exception ex)
        {
            LogError(ex);
        }
    
        return dt;
    }
    

    这是一个可以运行以查看返回数据的测试:

    for (int i = 0; i < dt.Rows.Count; i++)
    {
        for (int j = 0; j < dt.Rows[i].ItemArray.Length; j++)
        {
            Console.Write(dt.Rows[i].ItemArray[j] + ",");
        }
        Console.WriteLine();
    }
    

    另外,你提到设置超时...我通常在我的连接字符串中设置我,如下所示:

    "Server=SERVER;Database=DATABASE;User ID=USER;Password=PASSWORD;Trusted_Connection=False;Asynchronous Processing=true;Timeout=60;"
    

    您根本不需要额外的CommandFactory课程,除非您真的想要优化效果,否则您不需要设置MinimumCapacityMSDN)估计将返回多少条记录。此属性不常使用。