为什么 SqlDataReader 似乎修改了它的数据类型?
Why does SqlDataReader seem to modify the type of its data?
这个问题是 this DBA related question 之后的下一步。
我现在有以下 C# 代码,基于变量SqlCommand sqlCommand
和 SqlDataReader sqlDataReader
。
我是运行这段代码:
// What's the max difference of two "Own_Table" tupples for "Field_Name" column?
sqlCommand.CommandText = $"SELECT MAX(val - lag_value) FROM " +
$" (SELECT t.{Field_Name} AS val,LAG(t.{Field_Name}) " +
$" OVER(ORDER BY t.{Field_Name}) as lag_value " +
$" FROM {Own_Table} t) AS tmp " +
$"WHERE lag_value IS NOT NULL";
sqlCommand.Parameters.Clear();
sqlDataReader = sqlCommand.ExecuteReader();
long max_value = 0;
while (sqlDataReader.Read())
{
max_value = sqlDataReader.GetInt32(0); <== sometimes NOK
}
对于一个特定的字段,这似乎出错了:对于字段 Id
,提到的源代码行生成一个 System.InvalidCastException
,提到 Specific cast is not valid.
.
这是正确的,因为在立即 window 中,我可以看到以下结果:
? sqlDataReader.GetFieldType(0).ToString()
"System.Int64"
但是DataTable对应的列中的DataType
好像是System.Int32
,从下面直接window的摘录可以看出(dt_main
是DataTable
和i
表示对应列的索引):
? dt_main.Columns[i].DataType
{Name = "Int32" FullName = "System.Int32"}
在上一个具有相同 DataType
的专栏中,一切正常。
那么现在我的问题是:System.Int32
列的查询结果怎么可能突然决定将 System.Int64
作为数据类型,处理这个问题的最佳方法是什么? (我已经尝试用 sqlDataReader.GetInt64()
替换所有 sqlDataReader.GetInt32()
但这也失败了)。
DataTable dt_main
的结构从 INFORMATION_SCHEMA.COLUMNS
中检索如下:
sqlCommand.CommandText =
"SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS " +
"WHERE TABLE_NAME = @selectedItem";
sqlCommand.Parameters.Clear();
sqlCommand.Parameters.AddWithValue("selectedItem", cmb_Table_Names.SelectedItem);
// cmb_Table_Names contains all table names.
sqlDataReader = sqlCommand.ExecuteReader();
while (sqlDataReader.Read()) // Get the names of all the columns
{
string tmp_ColName = sqlDataReader.GetString(0);
string tmp_ColDataType = sqlDataReader.GetString(1);
Type T = typeof(string);
switch (tmp_ColDataType)
{
case "int": case "bigint": case "tinyint": case "smallint":
T = typeof(int);
break;
case "bit":
T = typeof(bool);
break;
case "varchar": case "datetime": case "text":
T = typeof(string);
break;
default:
T = typeof(string);
break;
}
dt_main.Columns.Add(tmp_ColName,T);
您分析架构信息的代码已损坏。这里:
case "int": case "bigint": case "tinyint": case "smallint":
T = typeof(int);
您假设 SQL 服务器类型 int
、bigint
、tinyint
和 smallint
都映射到 C# 类型 int
(即 .NET Framework 类型 Int32
)。
这是不正确的。例如,bigint
对应于 C# 的 long
,即 .NET Frameworks 的 Int64
.
您可以使用以下 MSDN 条目查找正确的映射:
这个问题是 this DBA related question 之后的下一步。
我现在有以下 C# 代码,基于变量SqlCommand sqlCommand
和 SqlDataReader sqlDataReader
。
我是运行这段代码:
// What's the max difference of two "Own_Table" tupples for "Field_Name" column?
sqlCommand.CommandText = $"SELECT MAX(val - lag_value) FROM " +
$" (SELECT t.{Field_Name} AS val,LAG(t.{Field_Name}) " +
$" OVER(ORDER BY t.{Field_Name}) as lag_value " +
$" FROM {Own_Table} t) AS tmp " +
$"WHERE lag_value IS NOT NULL";
sqlCommand.Parameters.Clear();
sqlDataReader = sqlCommand.ExecuteReader();
long max_value = 0;
while (sqlDataReader.Read())
{
max_value = sqlDataReader.GetInt32(0); <== sometimes NOK
}
对于一个特定的字段,这似乎出错了:对于字段 Id
,提到的源代码行生成一个 System.InvalidCastException
,提到 Specific cast is not valid.
.
这是正确的,因为在立即 window 中,我可以看到以下结果:
? sqlDataReader.GetFieldType(0).ToString()
"System.Int64"
但是DataTable对应的列中的DataType
好像是System.Int32
,从下面直接window的摘录可以看出(dt_main
是DataTable
和i
表示对应列的索引):
? dt_main.Columns[i].DataType
{Name = "Int32" FullName = "System.Int32"}
在上一个具有相同 DataType
的专栏中,一切正常。
那么现在我的问题是:System.Int32
列的查询结果怎么可能突然决定将 System.Int64
作为数据类型,处理这个问题的最佳方法是什么? (我已经尝试用 sqlDataReader.GetInt64()
替换所有 sqlDataReader.GetInt32()
但这也失败了)。
DataTable dt_main
的结构从 INFORMATION_SCHEMA.COLUMNS
中检索如下:
sqlCommand.CommandText =
"SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS " +
"WHERE TABLE_NAME = @selectedItem";
sqlCommand.Parameters.Clear();
sqlCommand.Parameters.AddWithValue("selectedItem", cmb_Table_Names.SelectedItem);
// cmb_Table_Names contains all table names.
sqlDataReader = sqlCommand.ExecuteReader();
while (sqlDataReader.Read()) // Get the names of all the columns
{
string tmp_ColName = sqlDataReader.GetString(0);
string tmp_ColDataType = sqlDataReader.GetString(1);
Type T = typeof(string);
switch (tmp_ColDataType)
{
case "int": case "bigint": case "tinyint": case "smallint":
T = typeof(int);
break;
case "bit":
T = typeof(bool);
break;
case "varchar": case "datetime": case "text":
T = typeof(string);
break;
default:
T = typeof(string);
break;
}
dt_main.Columns.Add(tmp_ColName,T);
您分析架构信息的代码已损坏。这里:
case "int": case "bigint": case "tinyint": case "smallint":
T = typeof(int);
您假设 SQL 服务器类型 int
、bigint
、tinyint
和 smallint
都映射到 C# 类型 int
(即 .NET Framework 类型 Int32
)。
这是不正确的。例如,bigint
对应于 C# 的 long
,即 .NET Frameworks 的 Int64
.
您可以使用以下 MSDN 条目查找正确的映射: