【问题标题】:Datatable always return second value数据表总是返回第二个值
【发布时间】:2014-12-17 13:41:25
【问题描述】:

我发现了一些我还没有找到解决方案的奇怪行为。当我调试 SQL 代码时,它返回正确的值,但是在 C# 代码中,数据表返回错误的结果。

由于这是计费应用程序并且它包含敏感信息,我无法发布整个代码,只能发布包含有问题代码的方法和返回结果的 SQL 存储过程。

SQL:

ALTER PROCEDURE [dbo].[conf_SetRationCurrency] 
-- Add the parameters for the stored procedure here

AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;

-- Insert statements for procedure here
DECLARE @Date AS VARCHAR(10),
      @Today AS VARCHAR(10)

SELECT @Date = CONVERT(VARCHAR(10),[date], 112) FROM RatioCurrency
SELECT @Today = CONVERT(VARCHAR(10),GETDATE(),112)

BEGIN TRAN
BEGIN TRY
   IF @Date <> @Today
   BEGIN
      -- INSERT
      INSERT INTO dbo.RatioCurrency 
      SELECT rateType, CAST(CONVERT(VARCHAR, GETDATE(), 112) AS SMALLDATETIME) AS [date],fromCurrency,toCurrency,value 
      FROM dbo.RatioCurrency where [date] = 
      (
      SELECT TOP 1 CAST(CONVERT(VARCHAR, [date], 112) AS SMALLDATETIME) AS [date] 
      FROM dbo.RatioCurrency 
      ORDER BY ID DESC
      )       
      SELECT 'Yes' AS 'INSERTED' -- return flag for setting output text in code
   END
   ELSE
   BEGIN
      SELECT 'No' AS 'NOT' -- return flag for setting output text in code 
   END
END TRY
BEGIN CATCH
   IF @@TRANCOUNT > 0
      ROLLBACK TRAN
      EXEC dbo.intf_ShowError
      RETURN
END CATCH
COMMIT
END

C#:

     DialogResult dialog = MessageBox.Show("Da li želite kopirati valutu zadnjeg unosa za današnji dan...?","Upit",MessageBoxButtons.YesNo, MessageBoxIcon.Question);
        if (dialog == DialogResult.Yes)
        {
            DataTable dt = Program.ExecProc("conf_SetRationCurrency");

            if (dt.Rows.Count > 0 && dt.Columns[0].ColumnName == "ErrorNumber")
            {
                Program.ShowDataInfoError(dt.Rows[0]); //print error message
            }
            else if (dt.Rows.Count > 0 && dt.Columns[0].ColumnName == "NOT") //part which should only give info that value is already in the database, no need to insert new one. 
            {
                SplashForm sf = new SplashForm();
                sf.informationText.Text = "Valuta već postoji.";
                sf.Show();
                GetCurrency();
                this.Refresh();
            }
            else // this part actually gives info that new values are inserted
            {
                SplashForm sf = new SplashForm();
                sf.informationText.Text = "Valuta je upisana.";
                sf.Show();
                GetCurrency();
                this.Refresh();
            }
        }
        else
        {
            return;
        }

即使 SQL 返回了正确的列名值,数据表也返回了列名 - “NOT”(第二个),我的意思是总是......这不可能是真的,因为我有 if/else 语句并且程序应该避免第二个声明。数据表对象怎么会持有错误的列名?这是一个错误还是因为我使用列的别名所以它使用最后一个......?有人回答吗?

【问题讨论】:

    标签: c# sql tsql datatable


    【解决方案1】:

    ADO.NET 正在缓存从存储过程返回的 DataTable 结构(列名和类型)。根据业务逻辑更改表结构不是一个好主意 - 而是改变数据而不是结构。 我建议您更改 sp 以便它始终返回相同的列名,例如“状态”,但 会根据您的业务逻辑而变化。

    --SQL logic
    if (errorCondition)
      SELECT 'ERROR' as Status, 'Error message' as Message
    if @Date <> @Today
       SELECT 'Yes' AS Status, '' AS Message
    else
       SELECT 'No' AS Status, '' as Message
    

    那么你的 C# 逻辑就变得更简单了:

    • 总是返回一行数据,列数固定,名称固定
    • 您可以在为您的业务逻辑返回的单行中使用

    【讨论】:

    • 我确实玩过代码,但结果相同,例如。 SELECT @val = 'Yes' ... ELSE BEGIN SELECT @val = 'No' END ... SELECT @val AS TEMP 和 C#:` dt.Columns[0].ColumnName == "TEMP" ` where dt.Rows[0][0].ToString().Equals("Yes"),仍然没有解决方案......它看起来像用户:evlive 是对的。它与跳过第一个值的指针有关
    • 对不起,我拼错了昵称 - 它是:@evilive
    • 如果您可以看到 DataTable 仅包含一行,并且您可以从该行中检索一个值,则没有被跳过的指针。您正在使用绝对索引访问行 [0],因此不涉及指针。好的,我认为问题出在您的第一条语句SELECT @Date = CONVERT(VARCHAR(10),[date], 112) FROM RatioCurrency 中,它将始终从表的第一行检索日期。仅当RatioCurrency 仅包含单行但在 SP 中您正在添加行时,它才会起作用,所以这是您的问题。
    • 好吧,我确实只需要一行来与当前日期进行比较。问题是如果插入不是自动完成的,您可以手动完成,所以首先它检查我更正为的最后一天:SELECT TOP 1 @Date = CONVERT(VARCHAR(10),[date], 112) FROM RatioCurrency ORDER BY id DESC 并将其与当前日期进行比较。如果它与插入不同,则应该发生,但如果不是,则跳过并仅发送 C# 代码的“标志”...
    【解决方案2】:

    曾经遇到过同样的问题,但在 C# 中没有:

    原因是通过php访问查询结果,指针已经被移动,所以第一个结果总是被跳过。

    听起来像同一种问题,可能是行数。

    (抱歉不能评论)

    【讨论】:

    • 好吧,我不能说它与行数有关,因为在 Visual Studio 中,当我将 DataTable 对象设置为“添加到手表”并查看他的属性时,我可以看到 RowCount 为 1,所以它有价值...
    猜你喜欢
    • 2016-10-28
    • 2021-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多