【问题标题】:DataTable Is Empty数据表为空
【发布时间】:2017-05-03 07:14:39
【问题描述】:

我正在尝试运行存储过程并将结果添加到数据表中。我的存储过程按原样执行,如果我从 SSMS 查询结果存储在其中的表 - 准确的结果就在那里。但是,我下面的代码每次都会产生numberofrecords = 0

我在下面的语法中错误地设置了什么?

using (conn = new SqlConnection(SQLConn))
{
using (cmd = new SqlCommand(storedprocname, conn))
{
  cmd.CommandType = CommandType.StoredProcedure;
  cmd.Parameters.Add("@Name", SqlDbType.VarChar, 100);
  cmd.Parameters.Add("d1", SqlDbType.Date, 100);
  cmd.Parameters.Add("d2", SqlDbType.Date, 100);
  cmd.Parameters["@Name"].Value = cboNames.Text.ToString();
  cmd.Parameters["d1"].Value = dtpd1.Value.ToString("MM/dd/yyyy");
  cmd.Parameters["d2"].Value = dtpd2.Value.ToString("MM/dd/yyyy");
  cmd.Parameters.Add("@Dolla", SqlDbType.VarChar, 100);
  cmd.Parameters["@Dolla"].Value = cboDolla.Text.ToString();

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

  int numberOfRecords = 0;
  numberOfRecords = dt.Select().Length;
  MessageBox.Show(numberOfRecords.ToString());
}

这些是我的类变量声明:

    public static SqlCommand cmd;
    public static SqlDataAdapter da;
    public static DataSet ds = new DataSet();
    public static DataTable dt = new DataTable();

编辑
这是我的存储过程,大约产生 32 行

ALTER Procedure [dbo].[TestParamQuery]
(
  @Name varchar(max)
  ,@d1 varchar(100)
  ,@d2 varchar(100)
  ,@dolla varchar(500)
)
As

Select 
EmployeeName
,EmployeeNumber
,CAST(hiredate As Date) [hire date]
,saleamount
FROM [TestDB].[dbo].[SalesFigs]
WHERE employeename = @Name
AND hiredate between @d1 AND @d2
AND saleamount >= @dolla

编辑 2
这就是我执行存储过程以确保它直接从 SSMS 内部返回我想要的结果的方式

USE [TestDB]
GO

DECLARE @return_value int

EXEC    @return_value = [dbo].[TestParamQuery]
        @Name = N'Sam Wise',
        @d1 = N'03/01/2016',
        @d2 = N'01/30/2016',
        @Dolla = N'1000'

SELECT  'Return Value' = @return_value

GO

【问题讨论】:

  • 显示 SP 代码也会很有帮助。
  • 我会避免声明那些类变量,而是在你的函数中声明它们,并输出DataTable作为函数返回值。
  • @JamesFaix - 我将它们声明为类变量,因为我在多个方法中使用它们,所以我没有在多个方法中多次声明,而是将它们用作类变量。例如,我有一种运行 SQL 存储过程的方法,它只将数据写入 SQL 表。然后我有一个单独的方法(上面那个),它运行一个返回数据的 SQL 存储过程(我尝试写入数据表)。使用类变量仍然不是一个好主意吗?
  • 一般情况下,我会尽量缩小每个变量的范围。对于这些变量,您每次运行方法(可能还有其他方法)时都会创建一个新实例,因此变量的每次使用都与其他使用无关。因此,我会将每个变量隐藏在使用它们的方法中。您可以按照您的方式保存几行代码,但您并没有避免任何开销,因为您仍然必须每次为每个变量初始化一个新实例。旧数据也有可能进入新方法调用。
  • @MichaelMormon 在方法内部,没有访问修饰符。声明的所有内容都只存在于该方法中。它比private 更私密。

标签: c# datatable dataadapter


【解决方案1】:

不知道为什么你不能得到值。但无论如何请尝试这种方法:

using (conn = new SqlConnection(SQLConn))
using (cmd = new SqlCommand(storedprocname, conn))
{
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.AddWithValue("@Name", cboNames.Text);
    cmd.Parameters.AddWithValue("d1", dtpd1.Value.ToShortDateString();
    cmd.Parameters.AddWithValue("d2", dtpd2.Value.ToShortDateString();
    cmd.Parameters.AddWithValue("@Dolla", cboDolla.Text);

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

    var numberOfRecords = dt.Rows.Count;
    MessageBox.Show(numberOfRecords);
}

【讨论】:

  • 与上述结果相同 numberOfRecords = 0
  • 当您使用 SSMS 运行时,您确定相同的参数返回数据吗?看来空结果是正确的结果。您可以尝试更改您提供给存储过程的值吗?
  • 我已多次更改变量。我已经单步执行了我的代码,并在 VS“Autos”窗口中,复制/粘贴在变量中传递的值并直接在 SSMS 中运行它,我得到返回的结果...
  • 在 SSMS 中运行时是执行存储过程还是只在其中运行查询?
  • 代码正确。所以问题不在c#代码中,也不在proc中。可能是错误的数据库
【解决方案2】:

不幸的是,SqlCommand 没有简单的方法或属性将命令转换为字符串,包括所有参数和值。我过去曾使用过这样的方法来简化调试命令:

public static string PrintCommand(this SqlCommand command){
    if (command == null) throw new ArgumentNullException("command");

    var sb = new StringBuilder();
    sb.AppendLine(command.CommandText); 
    foreach (var p in command.Parameters){
        sb.AppendLine("\t" + p.ParameterName + ": " + p.Value); 
    }
    return sb.ToString();
}

它应该输出这样的字符串:

"dbo.MyCommandName
    @Name: myNameParameterValue
    d1: 01/01/2016
    d2: 02/02/2016
    @Dolla: myDollaValue"

然后您可以像这样调用它,并在逐步调试器中检查值。

using (conn = new SqlConnection(SQLConn))
using (cmd = new SqlCommand(storedprocname, conn)) {
  cmd.CommandType = CommandType.StoredProcedure;
  cmd.Parameters.Add("@Name", SqlDbType.VarChar, 100);
  cmd.Parameters.Add("d1", SqlDbType.Date, 100);
  cmd.Parameters.Add("d2", SqlDbType.Date, 100);
  cmd.Parameters["@Name"].Value = cboNames.Text.ToString();
  cmd.Parameters["d1"].Value = dtpd1.Value.ToString("MM/dd/yyyy");
  cmd.Parameters["d2"].Value = dtpd2.Value.ToString("MM/dd/yyyy");
  cmd.Parameters.Add("@Dolla", SqlDbType.VarChar, 100);
  cmd.Parameters["@Dolla"].Value = cboDolla.Text.ToString();

  //Get a text representation here:
  var text = cmd.PrintCommand();

  //Put a breakpoint here to check the value:
  using (da = new SqlDataAdapter(cmd))
  {
    da.Fill(dt);
  }

  int numberOfRecords = 0;
  numberOfRecords = dt.Select().Length;
  MessageBox.Show(numberOfRecords.ToString());
}

【讨论】:

    猜你喜欢
    • 2016-02-24
    • 2014-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-18
    • 2019-05-01
    • 1970-01-01
    • 2021-11-05
    相关资源
    最近更新 更多