Odbc使用internalGetDate将String解析为Date?
Odbc parses String as Date using internalGetDate?
我正在尝试将我为 SQL 服务器连接编写的一些代码转换为使用 Odbc 数据源。我一直 运行 遇到了 OdbcDataReader.GetValue(int) 试图为字符串字段调用 OdbcDataReader.internalGetDate 的问题。
这是我目前用于获取值的代码:
private static void ReadRecord<T>(IDataRecord record, T myClass)
{
.... inside loop of datarecord fields ....
var value = record.GetValue(i);
pi.SetValue(myClass,
value == DBNull.Value
? null
: Convert.ChangeType(value, record.GetFieldType(i)), null);
当我使用 Odbc 针对特定 4D 数据 table 执行此操作时,我得到一个没有附加消息的 OdbcException。异常堆栈跟踪显示使用了 internalGetDate。
at System.Data.Odbc.OdbcConnection.HandleError(OdbcHandle hrHandle, RetCode retcode)
at System.Data.Odbc.OdbcDataReader.GetData(Int32 i, SQL_C sqlctype, Int32 cb, Int32& cbLengthOrIndicator)
at System.Data.Odbc.OdbcDataReader.GetData(Int32 i, SQL_C sqlctype)
at System.Data.Odbc.OdbcDataReader.internalGetDate(Int32 i)
at System.Data.Odbc.OdbcDataReader.GetValue(Int32 i, TypeMap typemap)
at System.Data.Odbc.OdbcDataReader.GetValue(Int32 i)
at System.Data.Odbc.DbCache.AccessIndex(Int32 i)
at System.Data.Odbc.OdbcDataReader.GetValue(Int32 i)
我查看了参考源 here,其中显示执行 GetSqlType 以确定在稍后的 GetValue() 调用中调用的函数。我写这段代码是为了检查有问题的索引的 SqlType
var odbcdatareader = typeof(OdbcDataReader);
var method = odbcdatareader.GetMethod("GetSqlType", BindingFlags.Instance | BindingFlags.NonPublic);
var type = method.Invoke(record, new object[] { i });
var typemap = odbcdatareader.Assembly.GetType("System.Data.Odbc.TypeMap");
var typemapodbctype = typemap.GetField("_odbcType", BindingFlags.Instance | BindingFlags.NonPublic);
var typemapdbtype = typemap.GetField("_dbType", BindingFlags.Instance | BindingFlags.NonPublic);
var typemaptype = typemap.GetField("_type", BindingFlags.Instance | BindingFlags.NonPublic);
var typemapsqltype = typemap.GetField("_sql_type", BindingFlags.Instance | BindingFlags.NonPublic);
Console.WriteLine("{0}, {1}, {2}, {3}", typemapodbctype.GetValue(type),
typemapdbtype.GetValue(type), typemaptype.GetValue(type),
typemapsqltype.GetValue(type));
这次检查的结果是:
Char, AnsiStringFixedLength, System.String, CHAR
为什么 Odbc 的 GetSqlType 将此报告为 CHAR,然后使用 internalGetDate 尝试解析数据?我是否遗漏了一些明显的东西?
更奇怪的是,当我在该索引上调用 GetString() 时,我也收到了 internalGetDate() 的错误。
at System.Data.Odbc.OdbcConnection.HandleError(OdbcHandle hrHandle, RetCode retcode)
at System.Data.Odbc.OdbcDataReader.GetData(Int32 i, SQL_C sqlctype, Int32 cb, Int32& cbLengthOrIndicator)
at System.Data.Odbc.OdbcDataReader.GetData(Int32 i, SQL_C sqlctype)
at System.Data.Odbc.OdbcDataReader.internalGetDate(Int32 i)
at System.Data.Odbc.OdbcDataReader.GetValue(Int32 i, TypeMap typemap)
at System.Data.Odbc.OdbcDataReader.GetValue(Int32 i)
at System.Data.Odbc.DbCache.AccessIndex(Int32 i)
at System.Data.Odbc.OdbcDataReader.internalGetString(Int32 i)
at System.Data.Odbc.OdbcDataReader.GetString(Int32 i)
这个问题实际上与数据库服务器(在本例中为 4D)将空日期关联为 00/00/0000 12:00:00 AM 的另一个问题有关。 DateTime 无法解析此日期,因此 OdbcDataReader 崩溃。我通过捕获异常并将我的 class 的 属性 设置为 null 解决了第一个问题,但这并没有解决根本问题。由于异常,DbCache 没有缓存值,并且由于 OdbcDataReader and DbCache works,系统必须遍历每个字段并获取它的数据。这是根本错误。 GetString 在 0..i 中循环并在 i-1 字段的 internalGetDate 上崩溃。
分辨率是....在我看来相当丑陋,但适合我的目的。
catch (ArgumentOutOfRangeException ex)
{
if (ex.Message == "Year, Month, and Day parameters describe an un-representable DateTime.")
{
pi.SetValue(myClass, null, null);
var odbcdatareader = typeof(OdbcDataReader);
var dataCache = odbcdatareader.GetField("dataCache",
BindingFlags.Instance | BindingFlags.NonPublic);
var dbcache = dataCache.GetValue(record);
var valuesfield = dbcache.GetType()
.GetField("_values", BindingFlags.Instance | BindingFlags.NonPublic);
var values = (object[]) valuesfield.GetValue(dbcache);
values[i] = new DateTime(1, 1, 1);
valuesfield.SetValue(dbcache, values);
}
else
throw;
}
我正在尝试将我为 SQL 服务器连接编写的一些代码转换为使用 Odbc 数据源。我一直 运行 遇到了 OdbcDataReader.GetValue(int) 试图为字符串字段调用 OdbcDataReader.internalGetDate 的问题。
这是我目前用于获取值的代码:
private static void ReadRecord<T>(IDataRecord record, T myClass)
{
.... inside loop of datarecord fields ....
var value = record.GetValue(i);
pi.SetValue(myClass,
value == DBNull.Value
? null
: Convert.ChangeType(value, record.GetFieldType(i)), null);
当我使用 Odbc 针对特定 4D 数据 table 执行此操作时,我得到一个没有附加消息的 OdbcException。异常堆栈跟踪显示使用了 internalGetDate。
at System.Data.Odbc.OdbcConnection.HandleError(OdbcHandle hrHandle, RetCode retcode)
at System.Data.Odbc.OdbcDataReader.GetData(Int32 i, SQL_C sqlctype, Int32 cb, Int32& cbLengthOrIndicator)
at System.Data.Odbc.OdbcDataReader.GetData(Int32 i, SQL_C sqlctype)
at System.Data.Odbc.OdbcDataReader.internalGetDate(Int32 i)
at System.Data.Odbc.OdbcDataReader.GetValue(Int32 i, TypeMap typemap)
at System.Data.Odbc.OdbcDataReader.GetValue(Int32 i)
at System.Data.Odbc.DbCache.AccessIndex(Int32 i)
at System.Data.Odbc.OdbcDataReader.GetValue(Int32 i)
我查看了参考源 here,其中显示执行 GetSqlType 以确定在稍后的 GetValue() 调用中调用的函数。我写这段代码是为了检查有问题的索引的 SqlType
var odbcdatareader = typeof(OdbcDataReader);
var method = odbcdatareader.GetMethod("GetSqlType", BindingFlags.Instance | BindingFlags.NonPublic);
var type = method.Invoke(record, new object[] { i });
var typemap = odbcdatareader.Assembly.GetType("System.Data.Odbc.TypeMap");
var typemapodbctype = typemap.GetField("_odbcType", BindingFlags.Instance | BindingFlags.NonPublic);
var typemapdbtype = typemap.GetField("_dbType", BindingFlags.Instance | BindingFlags.NonPublic);
var typemaptype = typemap.GetField("_type", BindingFlags.Instance | BindingFlags.NonPublic);
var typemapsqltype = typemap.GetField("_sql_type", BindingFlags.Instance | BindingFlags.NonPublic);
Console.WriteLine("{0}, {1}, {2}, {3}", typemapodbctype.GetValue(type),
typemapdbtype.GetValue(type), typemaptype.GetValue(type),
typemapsqltype.GetValue(type));
这次检查的结果是:
Char, AnsiStringFixedLength, System.String, CHAR
为什么 Odbc 的 GetSqlType 将此报告为 CHAR,然后使用 internalGetDate 尝试解析数据?我是否遗漏了一些明显的东西?
更奇怪的是,当我在该索引上调用 GetString() 时,我也收到了 internalGetDate() 的错误。
at System.Data.Odbc.OdbcConnection.HandleError(OdbcHandle hrHandle, RetCode retcode)
at System.Data.Odbc.OdbcDataReader.GetData(Int32 i, SQL_C sqlctype, Int32 cb, Int32& cbLengthOrIndicator)
at System.Data.Odbc.OdbcDataReader.GetData(Int32 i, SQL_C sqlctype)
at System.Data.Odbc.OdbcDataReader.internalGetDate(Int32 i)
at System.Data.Odbc.OdbcDataReader.GetValue(Int32 i, TypeMap typemap)
at System.Data.Odbc.OdbcDataReader.GetValue(Int32 i)
at System.Data.Odbc.DbCache.AccessIndex(Int32 i)
at System.Data.Odbc.OdbcDataReader.internalGetString(Int32 i)
at System.Data.Odbc.OdbcDataReader.GetString(Int32 i)
这个问题实际上与数据库服务器(在本例中为 4D)将空日期关联为 00/00/0000 12:00:00 AM 的另一个问题有关。 DateTime 无法解析此日期,因此 OdbcDataReader 崩溃。我通过捕获异常并将我的 class 的 属性 设置为 null 解决了第一个问题,但这并没有解决根本问题。由于异常,DbCache 没有缓存值,并且由于 OdbcDataReader and DbCache works,系统必须遍历每个字段并获取它的数据。这是根本错误。 GetString 在 0..i 中循环并在 i-1 字段的 internalGetDate 上崩溃。
分辨率是....在我看来相当丑陋,但适合我的目的。
catch (ArgumentOutOfRangeException ex)
{
if (ex.Message == "Year, Month, and Day parameters describe an un-representable DateTime.")
{
pi.SetValue(myClass, null, null);
var odbcdatareader = typeof(OdbcDataReader);
var dataCache = odbcdatareader.GetField("dataCache",
BindingFlags.Instance | BindingFlags.NonPublic);
var dbcache = dataCache.GetValue(record);
var valuesfield = dbcache.GetType()
.GetField("_values", BindingFlags.Instance | BindingFlags.NonPublic);
var values = (object[]) valuesfield.GetValue(dbcache);
values[i] = new DateTime(1, 1, 1);
valuesfield.SetValue(dbcache, values);
}
else
throw;
}