【问题标题】:Procedure Returning Blank Data Table from ASP.NET从 ASP.NET 返回空白数据表的过程
【发布时间】:2018-04-18 18:53:43
【问题描述】:

我尝试从 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 中运行该过程时,我工作得很好。

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

按照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.设置不计数

2.使用数据适配器代替数据读取器

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

就像我之前提到的,存储过程中包含的查询是巨大的,我没有将它包含在此处,因为它的大小和这篇文章已经足够长了。我再次确认该程序在 SSMS 中运行。

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

感谢您提供的任何帮助。

更新:

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

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

我想我会在遇到它们时提供线索。

【问题讨论】:

    标签: c# datatable sqlcommand


    【解决方案1】:

    你已经很接近了。这里有几点建议:

    1. SqlConnection 永远不会打开。您需要致电.Open() 订购 以便建立连接。
    2. 如果您设置 .Fill() 行上的断点并将鼠标悬停在 DataTable 对象,它看起来好像DataTable 是空的(如您所见),但.Fill() 实际上为您填充了DataTableRows 自动(见MSDN)。我敢打赌,如果你遍历Rows,你会发现 您的查询实际上一直在返回数据。
    3. 您可以使用using 语句自动为您调用.Dispose() 以及关闭SqlConnection

    这是您方法的更新版本:

    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();
    }
    

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

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

    你根本不需要那个额外的CommandFactory 类,也不需要设置MinimumCapacity (MSDN),除非你真的想优化性能并猜测有多少记录将被退回。此属性不经常使用。

    【讨论】:

    • 感谢您的建议。不幸的是,该命令的结果仍然是一个空白的 {} 数据表。
    • 不想让你悬空——有机会我会再看看这个。
    • 欣赏一下兄弟。
    • 非常有趣。我看到命令工厂类是不必要的。当我实施您的建议时,它仍然为原始查询返回了一个空白数据表,但对于我在编辑中提到的第二个查询,它按预期返回了 7 行。我确认原始查询在 SSMS 中工作,所以我有点困惑。我会做更多的挖掘。不过谢谢你,你帮了大忙
    • 不客气。您能否发布仍然无法正常工作的更新代码?您在测试中传递的 @practiceID 值是否与在 SSMS 中相同?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-11
    • 1970-01-01
    • 2020-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多