jonwagner / Insight.Database

Fast, lightweight .NET micro-ORM
Other
861 stars 145 forks source link

DB2 and IDbColumnSchemaGenerator #382

Closed brianchance closed 6 years ago

brianchance commented 6 years ago

Describe the bug

Getting an error working with DB2.

Unable to cast object of type 'IBM.Data.DB2.Core.DB2DataReader' to type 'System.Data.Common.IDbColumnSchemaGenerator'.
   at Insight.Database.Providers.DB2.DB2InsightDbProvider.IsXmlColumn(IDataReader reader, Int32 index)
   at Insight.Database.DbSerializationRule.GetSerializer(IDataReader reader, Int32 column, ClassPropInfo prop)
   at Insight.Database.ColumnMapping.MapColumn(Type type, IDataReader reader, Int32 column, IColumnMapper overrideMapping)
   at System.Linq.Enumerable.SelectIPartitionIterator`2.PreallocatingToArray(Int32 count)
   at System.Linq.Enumerable.SelectIPartitionIterator`2.ToArray()
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   at Insight.Database.ColumnMapping.MapColumns(Type type, IDataReader reader, Int32 startColumn, Nullable`1 columnCount, IColumnMapper overrideMapping)
   at Insight.Database.CodeGenerator.ClassDeserializerGenerator.MapColumns(Type type, IDataReader reader, Int32 startColumn, Int32 columnCount, IRecordStructure structure, Boolean allowBindChild)
   at Insight.Database.CodeGenerator.ClassDeserializerGenerator.CreateClassDeserializerDynamicMethod(Type type, IDataReader reader, IRecordStructure structure, Int32 startColumn, Int32 columnCount, Boolean createNewObject, Boolean isRootObject, Boolean allowBindChild)
   at Insight.Database.CodeGenerator.ClassDeserializerGenerator.CreateClassDeserializer(Type type, IDataReader reader, IRecordStructure structure, Int32 startColumn, Int32 columnCount, Boolean createNewObject)
   at Insight.Database.CodeGenerator.ClassDeserializerGenerator.CreateDeserializer(IDataReader reader, Type type, IRecordStructure structure, SchemaMappingType mappingType)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Insight.Database.CodeGenerator.DbReaderDeserializer.GetDeserializer(IDataReader reader, Type type, IRecordStructure structure, SchemaMappingType mappingType)
   at Insight.Database.CodeGenerator.DbReaderDeserializer.GetDeserializer[T](IDataReader reader, IRecordStructure structure)
   at Insight.Database.DBConnectionExtensions.AsyncReader`1.MoveNextAsync()
   at Insight.Database.DBConnectionExtensions.ToListAsync[T](IDataReader reader, IRecordReader`1 recordReader, CancellationToken cancellationToken, Boolean firstRecordOnly)
   at Insight.Database.Structure.ListReader`1.ReadAsync(IDbCommand command, IDataReader reader, CancellationToken cancellationToken)
   at Insight.Database.DBConnectionExtensions.ExecuteAsyncAndAutoClose[T](IDbConnection connection, Object parameters, Func`2 getCommand, Boolean callGetReader, Func`3 translate, CommandBehavior commandBehavior, CancellationToken cancellationToken, Object outputParameters)

Looking at the IBM.Data.DB2.Core source, the DB2DataReader does not implement IDbColumnSchemaGenerator. Looking at DB2InsightDbProvider.IsXmlColumn, it also does not implement GetSchemaTable.

Digging down, I see that there is an internal DB2Type GetDB2Type(int i) which is of no use. There is however a public override string GetDataTypeName(int i) from DbDataReader which returns the TypeName instead of the DB2Type of same the underlying structure as DB2Type. Based on the rest of their code, it should return "XML".

Maybe IsXmlColumn would be... return ((DbDataReader)reader).GetDataTypeName(index) == "XML"

Steps to reproduce

Any extension methods on reader or query i.e. 'return await GetConnection().QuerySqlAsync("select col from table");`

jonwagner commented 6 years ago

It looks like I lost all of the test cases for DB2 when we upgraded to .net core support. Let me see what I can do with this issue.

brianchance commented 6 years ago

As a test, I inherited from DB2InsightDbProvider and overrode IsXmlColumn with return string.Compare(((DbDataReader)reader).GetDataTypeName(index), "XML", StringComparison.OrdinalIgnoreCase) == 0;

Seems to work.

jonwagner commented 6 years ago

The code in master has been updated. Now I just have to find time to run a build.

jonwagner commented 6 years ago

This is fixed in v6.2.6, available now.

brianchance commented 6 years ago

@jonwagner - works, thank you.