从 ASP.NET 返回空白数据 Table 的过程
Procedure Returning Blank Data Table from ASP.NET
我在尝试从 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以调整执行超时限制。
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
是否正确初始化。调整之后,我开始遇到命令 returns 空白数据 table 的问题。我假设它可能与数据的最小容量有关 table dt
,所以我调整了它,正如您在原始代码中看到的那样。
我已经进行了额外的研究,并提出了建议的修复方法但没有用:
1. 设置无计数
2. 使用数据适配器代替数据 reader
3.这是最详细的回答。论坛中提出了一些建议,但最终的解决方案与数据库默认使用的视图和阻止对所需数据的访问有关。我已经与我们的 DBA 确认我们不会这样做。
正如我之前提到的,包含在存储过程中的查询非常庞大,我没有将其包含在此处,因为它的大小非常庞大,而且这个 post 本身已经足够长了。再一次,我确实确认该过程在 SSMS 中有效。
我也没有包含示例结果集,因为数据包含受限信息。
感谢您提供的任何帮助。
更新:
我添加了另一种调用存储过程的方法,以查看问题是否特定于被调用的特定过程。第二个存储过程也返回了空白数据 table,因此问题并非特定于任何一个过程。 (我还确认第二个过程正在运行并在 SSMS 中返回行)
这让我相信该项目的 app.config 文件有问题。然后我添加了第三种方法,该方法调用解决方案中另一个项目的存储过程。但是,即使那样也返回了空白数据 table.
我想我会在遇到它们时提供线索。
你很接近。这里有一些提示:
SqlConnection
从未打开过。您需要按顺序调用 .Open()
用于建立连接。
- 如果你设置
.Fill()
行上的断点并将鼠标悬停在 DataTable
上
对象,它看起来好像 DataTable
是空的(如您所见),但 .Fill()
实际上为您填充了 DataTable
的 Rows
自动(参见 MSDN)。我敢打赌,如果你遍历 Rows
,你会发现
您的查询实际上一直在返回数据。
- 您可以使用
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();
}
此外,您提到设置超时...我通常在我的连接字符串中设置我的,如下所示:
"Server=SERVER;Database=DATABASE;User ID=USER;Password=PASSWORD;Trusted_Connection=False;Asynchronous Processing=true;Timeout=60;"
你根本不需要那个额外的 CommandFactory
class,你也不需要设置 MinimumCapacity
(MSDN) 除非你真的尝试优化性能并估计将返回多少条记录。这个 属性 不常使用。
我在尝试从 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以调整执行超时限制。
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
是否正确初始化。调整之后,我开始遇到命令 returns 空白数据 table 的问题。我假设它可能与数据的最小容量有关 table dt
,所以我调整了它,正如您在原始代码中看到的那样。
我已经进行了额外的研究,并提出了建议的修复方法但没有用:
1. 设置无计数
2. 使用数据适配器代替数据 reader
3.这是最详细的回答。论坛中提出了一些建议,但最终的解决方案与数据库默认使用的视图和阻止对所需数据的访问有关。我已经与我们的 DBA 确认我们不会这样做。
正如我之前提到的,包含在存储过程中的查询非常庞大,我没有将其包含在此处,因为它的大小非常庞大,而且这个 post 本身已经足够长了。再一次,我确实确认该过程在 SSMS 中有效。
我也没有包含示例结果集,因为数据包含受限信息。
感谢您提供的任何帮助。
更新:
我添加了另一种调用存储过程的方法,以查看问题是否特定于被调用的特定过程。第二个存储过程也返回了空白数据 table,因此问题并非特定于任何一个过程。 (我还确认第二个过程正在运行并在 SSMS 中返回行)
这让我相信该项目的 app.config 文件有问题。然后我添加了第三种方法,该方法调用解决方案中另一个项目的存储过程。但是,即使那样也返回了空白数据 table.
我想我会在遇到它们时提供线索。
你很接近。这里有一些提示:
SqlConnection
从未打开过。您需要按顺序调用.Open()
用于建立连接。- 如果你设置
.Fill()
行上的断点并将鼠标悬停在DataTable
上 对象,它看起来好像DataTable
是空的(如您所见),但.Fill()
实际上为您填充了DataTable
的Rows
自动(参见 MSDN)。我敢打赌,如果你遍历Rows
,你会发现 您的查询实际上一直在返回数据。 - 您可以使用
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();
}
此外,您提到设置超时...我通常在我的连接字符串中设置我的,如下所示:
"Server=SERVER;Database=DATABASE;User ID=USER;Password=PASSWORD;Trusted_Connection=False;Asynchronous Processing=true;Timeout=60;"
你根本不需要那个额外的 CommandFactory
class,你也不需要设置 MinimumCapacity
(MSDN) 除非你真的尝试优化性能并估计将返回多少条记录。这个 属性 不常使用。