Closed DSANTIMORE closed 4 years ago
Could you post a repro?
I can't post a full working repro, but here's the anonymized code. Note that "StoredProcA" and "StoredProcB" apparently select against the same DB table; unsure if that is relevant here. However, the documentation and syntax suggests we're limiting the mapping to a specified C# type.
`public class MyRepo { private readonly string _connectionString;
public MyRepo(string connectionString)
{
if(String.IsNullOrWhiteSpace(connectionString))
throw new ArgumentNullException(nameof(connectionString));
_connectionString = connectionString;
//Make sure that the correct provider is registered. This goes wrong at times in multi-assembly scenarios.
SqlInsightDbProvider.RegisterProvider();
ColumnMapping.Tables.RemoveStrings<TypeA>("_");
}
public TypeB GetTypeB(typeBId)
{
//ArgumentNull exception is thrown here.
//No mapping is required on TypeB.
//Stack trace:
/*
at Insight.Database.RegexReplaceTransform`1.TransformDatabaseName(Type type, String databaseName)
at System.Linq.Enumerable.Aggregate[TSource,TAccumulate](IEnumerable`1 source, TAccumulate seed, Func`3 func)
at Insight.Database.ColumnMapping.MapColumn(Type type, IDataReader reader, Int32 column, IColumnMapper overrideMapping)
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
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.DBReaderExtensions.Single[T](IDataReader reader, IRecordReader`1 recordReader)
at Insight.Database.Structure.SingleReader`1.Read(IDbCommand command, IDataReader reader)
at Insight.Database.DBConnectionExtensions.<>c__DisplayClass168_0`1.<Query>b__1(IDbCommand cmd, IDataReader r)
at Insight.Database.DBConnectionExtensions.ExecuteAndAutoClose[T](IDbConnection connection, Func`2 getCommand, Func`3 translate, CommandBehavior commandBehavior)
at Insight.Database.DBConnectionExtensions.Query[T](IDbConnection connection, String sql, Object parameters, IQueryReader`1 returns, CommandType commandType, CommandBehavior commandBehavior, Nullable`1 commandTimeout, IDbTransaction transaction, Object outputParameters)
at Insight.Database.DBConnectionExtensions.Single[T1](IDbConnection connection, String sql, Object parameters, CommandType commandType, CommandBehavior commandBehavior, Nullable`1 commandTimeout, IDbTransaction transaction, Object outputParameters)
at Blah.Blah.Blah.GetTypeB(Int32 typeBId) in Blah
*/
return new SqlConnection(_connectionString).Single<TypeB>("StoredProcB", id:typeBId);
}
public TypeA GetTypeA(typeAId)
{
return new SqlConnection(_connectionString).Single<TypeA>("StoredProcA", id:typeAId);
}
}`
I've confirmed that the problem persists even if the "StoredProcA" selects against a completely different table.
It seems that having any ColumnMapping.Tables registered sends the code down a different path that expects something regardless of the c# type being materialized.
Yeah it's possible that it's going down another code path. I won't have time to dive in for the next few weeks, but if someone dives in and makes a fix, I can do a build.
I will attempt to look into it this week.
I put a potential fix for this in 6.2.11
When using type-constraint helper methods (e.g., ColumnMapping.Tables.RemoveString("_")), I end up with ArgumentNullExceptions in TransformDatabaseName() on unrelated types.
As far as I can tell, when using ColumnMapping.Tables.RemoveStrings("_"), this is having a magical effect when attempting to use Query< TypeB >(). When I comment out all of the ColumnMapping... methods, the problem goes away (but of course, TypeA is not mapped correctly anymore).
Specifically, I get a runtime ArgumentNullException in TransformDatabaseName indicating databaseName is null.
Steps to reproduce (if applicable)