ADO.NET - SQL 位值“1”仍被 DataReader 读取为 "false"
ADO.NET - SQL bit value "1" still being read as "false" by DataReader
如果我 运行 来自 SSMS 的存储过程,我可以清楚地看到相关列中的 1
(在 ADO 中应该 return true
),但是在我的中间层时,DataReader
总是 returns false
。我担心这可能是因为我在 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
IDataRecord.GetBoolean
方法要求该值已经是一个布尔值。它不会尝试转换它。您可以使用以下代码获取布尔值:
Convert.ToBoolean(record.GetValue(record.GetOrdinal("WasAdjusted")))
确保执行存储过程的用户具有same/equal权限。应用程序用户(执行 IDataReader
)可能具有与您个人用于登录 SSMS 的帐户不同的权限,在这种情况下,相同的存储过程将提供两个不同的结果集。
如果我 运行 来自 SSMS 的存储过程,我可以清楚地看到相关列中的 1
(在 ADO 中应该 return true
),但是在我的中间层时,DataReader
总是 returns false
。我担心这可能是因为我在 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
IDataRecord.GetBoolean
方法要求该值已经是一个布尔值。它不会尝试转换它。您可以使用以下代码获取布尔值:
Convert.ToBoolean(record.GetValue(record.GetOrdinal("WasAdjusted")))
确保执行存储过程的用户具有same/equal权限。应用程序用户(执行 IDataReader
)可能具有与您个人用于登录 SSMS 的帐户不同的权限,在这种情况下,相同的存储过程将提供两个不同的结果集。