Odbc使用internalGetDate将字符串解析为日期?
问题描述:
我正在尝试将我为SQL Server连接编写的代码进行转换以使用Odbc数据源。我已经遇到了OdbcDataReader.GetValue(int)尝试为字符串字段调用OdbcDataReader.internalGetDate的问题。Odbc使用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数据表,我得到一个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使用internalGetDate尝试被报道这是一个CHAR但随后并解析数据?我错过了明显的东西吗?
Even weirder是当我在该索引上调用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崩溃。我通过捕获异常并将我的类的属性设置为null来解决了第一个问题,但这并没有解决潜在的问题。 DbCache由于异常而没有缓存该值,并且由于系统必须循环遍历每个字段并获取它的数据。这是潜在的错误。 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;
}
问题..你通过ODBC访问什么类型的数据库..?是这个Sql Server ..?如果是这样,那么为什么不远离'System.Data.Odbc'对象并使用SqlClient数据对象。 – MethodMan