【问题标题】:ADO.NET - SQL bit value "1" still being read as "false" by DataReaderADO.NET - SQL 位值“1”仍被 DataReader 读取为“假”
【发布时间】:2017-04-19 00:48:22
【问题描述】:

如果我从 SSMS 运行我的存储过程,我可以在相关列中清楚地看到 1(在 ADO 中应该返回 true),但是在我的中间层中,DataReader 总是返回 @987654325 @。我担心这可能是因为我在我的SELECT 语句中将值转换为bit,但是如果我将CASE 语句更改为CAST(1 AS BIT)DataReader 正确读取所有内容为true,所以这不是选角。 [为此向@MikhailLobanov 致敬]

这是我的 SQL 脚本:

SELECT CASE
    WHEN receiptid IS NULL THEN CAST(0 AS BIT)
    ELSE CAST(1 AS BIT)
END [WasAdjusted]
FROM dbo.MyTable

UNION ALL

SELECT CONVERT(BIT, 0) [WasAdjusted]
FROM dbo.MySecondTable

然后这是我的 ADO.NET C# 代码:

Func<IDataRecord, ResponseModel> searchReader = delegate (IDataRecord record)
{
    var model = new ResponseModel();
    model.BooleanProperty = record.GetBoolean(0);    
    return model;
};

有人问周边的代码,所以这里是我的DataReader

protected static List<TReturnType> ExecuteReader<TReturnType>(string connectionString, string storedProcName, Func<IDataRecord, TReturnType> delegateFunction, List<SqlParameter> collection = null)
{
    List<TReturnType> results = null;

    try
    {
        using (SqlConnection connect = new SqlConnection(connectionString))
        {
            connect.Open();

            SqlCommand command = new SqlCommand(storedProcName, connect);
            command.CommandTimeout = 1000;
            command.CommandType = CommandType.StoredProcedure;

            if (collection != null)
            {
                collection.ForEach(x => command.Parameters.Add(x));
            }

            using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection))
            {
                while (reader.Read())
                {
                    if (results == null)
                    {
                        results = new List<TReturnType>();
                    }

                    results.Add(delegateFunction((IDataRecord)reader));
                }

                reader.Close();
            }

            connect.Dispose();
        }
    }
    catch (Exception ex)
    {
        throw new Exception(ex.Message);
    }

    return results;
}

然后你这样称呼它:

return ExecuteReader(_connectionString, "dbo.NameOfStoredProc", searchReader, sqlParams);

我错过了什么?谢谢。

编辑 2017-04-25:看起来其他人可能有同样的问题:https://github.com/AutoMapper/AutoMapper.Data/issues/12

【问题讨论】:

  • 您可能需要为您的列命名(为该列提供别名)?
  • @Shnugo 我的专栏 (FWIW) 的名称是 WasAdjusted。我试过做record.GetBoolean(record.GetOrdinal("WasAdjusted")),但这给了我同样的结果。我将更新我的问题以显示。
  • 为什么要将一些值转换为位?你只需要两个不同的值,为什么不只返回一些像'T'/'F'和record.GetString(0)
  • @lei-yang 这不是一个糟糕的 hack;如果没有其他解决方案,我可能不得不这样做。如果您没有明确地将它们转换为 bit SQL 会自动假定它们是整数 int
  • 试试SELECT CAST(1 AS BIT) AS WasAdjusted 调试起来容易很多

标签: c# sql-server ado.net sqldatareader


【解决方案1】:

确保执行存储过程的用户具有相同/相等的权限。应用程序用户(执行IDataReader)可能具有与您个人用于登录 SSMS 的帐户不同的权限,在这种情况下,相同的存储过程将提供两个不同的结果集。

【讨论】:

  • 我也有同样的问题。我在 SSMS 中使用与 Visual Studio 相同的登录帐户,但结果不同:/
【解决方案2】:

IDataRecord.GetBoolean 方法要求该值已经是一个布尔值。它不会尝试转换它。您可以使用以下代码获取布尔值: Convert.ToBoolean(record.GetValue(record.GetOrdinal("WasAdjusted")))

【讨论】:

  • 问题是record.GetValue(record.GetOrdinal("WasAdjusted"))在应该是true时返回false,而不是它不能识别布尔值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多