我有一个循环遍历从 MySqlCommand 生成的 DataReader,它的查询从一些字段中选择,包括 2 TINYINT(1)
映射到 bool
的字段s 在 C# 上,这正是我所期望的。
当我将查询更改为执行 UNION ALL
时出现了问题同一张 table 。
更改查询后,我开始收到无效转换错误。 TINYINT(1)
列现在返回 SByte
s 而不是 Boolean
.
这是 MySql 服务器的问题吗? MySql 网络/连接器问题?这是预期的行为吗?
示例查询:
string sql = @"SELECT tinyint1column FROM mytable WHERE id = 1";
command.CommandText = sql;
using(var reader = command.ExecuteReader())
{
while(reader.Read())
{
bool flag = (bool)reader["tinyint1column"]; // OK - No error
}
}
sql = @"SELECT tinyint1column FROM mytable WHERE id = 1
UNION ALL
SELECT tinyint1column FROM mytable WHERE id = 2";
command.CommandText = sql;
using(var reader = command.ExecuteReader())
{
while(reader.Read())
{
bool flag = (bool)reader["tinyint1column"]; // Invalid cast error???
}
}
在有人提问之前:
- 我在共享主机上安装了 MySql Server 5.1,因此无法升级服务器。
- 我使用的是 MySql.Data 版本 6.5.4,因为它是我唯一可以编译并以中等/部分推力在此共享主机上运行的版本。
- 我实际上是在将读者“转换”到
List<DbDataRecord>
与.Cast<>()
获取“断开连接的阅读器”的扩展方法,但它不会以任何方式更改基础数据。
最佳答案
我也可以通过 NET Connector 6.3 确认问题(?)。
然而,调用 reader.GetBoolean()
有一个简单的方法。
MySql 连接器中基本 IDbDataReader 的重写在读取器字段上内部调用 Convert.ToBoolean()
public bool GetBoolean(string name)
{
return this.GetBoolean(this.GetOrdinal(name));
}
public override bool GetBoolean(int i)
{
return Convert.ToBoolean(this.GetValue(i));
}
因此您可以轻松地调整您的代码以适应这种情况(并且它也适用于您的查询的单表版本)
using(var reader = command.ExecuteReader())
{
while(reader.Read())
{
bool flag = reader.GetBoolean("tinyint1column");
....
}
}
编辑 鉴于您在下方的评论,我认为您可以使用 DbDataRecord 类的扩展方法解决缺少 GetBoolean(fieldName) 的问题。
我已经使用 LinqPad 对此进行了测试,它似乎可以正常工作(如果该字段为 null,则返回内容的一部分)
public bool GetBoolean(DbDataRecord rec, string fieldName)
{
int pos = rec.GetOrdinal(fieldName);
if(rec.IsDBNull(pos))
return false; // ??
object result = rec.GetValue(pos);
return Convert.ToBoolean(result);
}
关于c# - 如果使用 UNION ALL,MySqlDataReader 会为同一列返回不同的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27808304/