From 96bebb9c084ea4d2b4321d090638839ec7efb737 Mon Sep 17 00:00:00 2001 From: "lyonspride3@gmail.com" Date: Sat, 19 Jul 2014 11:58:27 -0800 Subject: [PATCH 1/3] This allows DefaultTypeMap to search for columns that use "_" to separate words as an alternative to camel case. --- Dapper NET40/SqlMapper.cs | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/Dapper NET40/SqlMapper.cs b/Dapper NET40/SqlMapper.cs index 6c322c313..3d38f6db2 100644 --- a/Dapper NET40/SqlMapper.cs +++ b/Dapper NET40/SqlMapper.cs @@ -4457,14 +4457,40 @@ public SqlMapper.IMemberMap GetConstructorParameter(ConstructorInfo constructor, /// Mapping implementation public SqlMapper.IMemberMap GetMember(string columnName) { - var property = _properties.FirstOrDefault(p => string.Equals(p.Name, columnName, StringComparison.Ordinal)) - ?? _properties.FirstOrDefault(p => string.Equals(p.Name, columnName, StringComparison.OrdinalIgnoreCase)); + SqlMapper.IMemberMap m = this.GetMember(columnName, columnName); + + if (m != null) + return m; + + //work around for databases that make it difficult to use camel case in column names such as DB2 + if (columnName.Contains("_")) + { + string c = columnName.Replace("_", string.Empty); + m = this.GetMember(c, columnName); + + if (m != null) + return m; + } + + return null; + } + + /// + /// Gets member mapping for columnName by looking for a member named searchColumnName + /// + /// The column name to search for + /// DataReader column name + /// Mapping implementation + private SqlMapper.IMemberMap GetMember(string searchColumnName, string columnName) + { + var property = _properties.FirstOrDefault(p => string.Equals(p.Name, searchColumnName, StringComparison.Ordinal)) + ?? _properties.FirstOrDefault(p => string.Equals(p.Name, searchColumnName, StringComparison.OrdinalIgnoreCase)); if (property != null) return new SimpleMemberMap(columnName, property); - var field = _fields.FirstOrDefault(p => string.Equals(p.Name, columnName, StringComparison.Ordinal)) - ?? _fields.FirstOrDefault(p => string.Equals(p.Name, columnName, StringComparison.OrdinalIgnoreCase)); + var field = _fields.FirstOrDefault(p => string.Equals(p.Name, searchColumnName, StringComparison.Ordinal)) + ?? _fields.FirstOrDefault(p => string.Equals(p.Name, searchColumnName, StringComparison.OrdinalIgnoreCase)); if (field != null) return new SimpleMemberMap(columnName, field); From 53d0fc6fa303180d42f4bb3d920df89018aa49f3 Mon Sep 17 00:00:00 2001 From: "lyonspride3@gmail.com" Date: Thu, 24 Jul 2014 11:29:02 -0800 Subject: [PATCH 2/3] Revert "This allows DefaultTypeMap to search for columns that use "_" to separate words as an alternative to camel case." This reverts commit 96bebb9c084ea4d2b4321d090638839ec7efb737. --- Dapper NET40/SqlMapper.cs | 34 ++++------------------------------ 1 file changed, 4 insertions(+), 30 deletions(-) diff --git a/Dapper NET40/SqlMapper.cs b/Dapper NET40/SqlMapper.cs index 3d38f6db2..6c322c313 100644 --- a/Dapper NET40/SqlMapper.cs +++ b/Dapper NET40/SqlMapper.cs @@ -4457,40 +4457,14 @@ public SqlMapper.IMemberMap GetConstructorParameter(ConstructorInfo constructor, /// Mapping implementation public SqlMapper.IMemberMap GetMember(string columnName) { - SqlMapper.IMemberMap m = this.GetMember(columnName, columnName); - - if (m != null) - return m; - - //work around for databases that make it difficult to use camel case in column names such as DB2 - if (columnName.Contains("_")) - { - string c = columnName.Replace("_", string.Empty); - m = this.GetMember(c, columnName); - - if (m != null) - return m; - } - - return null; - } - - /// - /// Gets member mapping for columnName by looking for a member named searchColumnName - /// - /// The column name to search for - /// DataReader column name - /// Mapping implementation - private SqlMapper.IMemberMap GetMember(string searchColumnName, string columnName) - { - var property = _properties.FirstOrDefault(p => string.Equals(p.Name, searchColumnName, StringComparison.Ordinal)) - ?? _properties.FirstOrDefault(p => string.Equals(p.Name, searchColumnName, StringComparison.OrdinalIgnoreCase)); + var property = _properties.FirstOrDefault(p => string.Equals(p.Name, columnName, StringComparison.Ordinal)) + ?? _properties.FirstOrDefault(p => string.Equals(p.Name, columnName, StringComparison.OrdinalIgnoreCase)); if (property != null) return new SimpleMemberMap(columnName, property); - var field = _fields.FirstOrDefault(p => string.Equals(p.Name, searchColumnName, StringComparison.Ordinal)) - ?? _fields.FirstOrDefault(p => string.Equals(p.Name, searchColumnName, StringComparison.OrdinalIgnoreCase)); + var field = _fields.FirstOrDefault(p => string.Equals(p.Name, columnName, StringComparison.Ordinal)) + ?? _fields.FirstOrDefault(p => string.Equals(p.Name, columnName, StringComparison.OrdinalIgnoreCase)); if (field != null) return new SimpleMemberMap(columnName, field); From d56296e3f89e80e9d44ff17a144de6196970046b Mon Sep 17 00:00:00 2001 From: "lyonspride3@gmail.com" Date: Thu, 24 Jul 2014 12:37:57 -0800 Subject: [PATCH 3/3] Allow creation of new default type maps --- Dapper NET40/SqlMapper.cs | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/Dapper NET40/SqlMapper.cs b/Dapper NET40/SqlMapper.cs index 6c322c313..6c7e27e3c 100644 --- a/Dapper NET40/SqlMapper.cs +++ b/Dapper NET40/SqlMapper.cs @@ -582,6 +582,8 @@ where pair.Value > 1 static SqlMapper() { + SetDefaultTypeMap(t => new DefaultTypeMap(t)); + typeMap = new Dictionary(); typeMap[typeof(byte)] = DbType.Byte; typeMap[typeof(sbyte)] = DbType.SByte; @@ -2928,7 +2930,7 @@ static readonly MethodInfo getItem = typeof(IDataRecord).GetProperties(BindingFlags.Instance | BindingFlags.Public) .Where(p => p.GetIndexParameters().Any() && p.GetIndexParameters()[0].ParameterType == typeof(int)) .Select(p => p.GetGetMethod()).First(); - + /// /// Gets type-map for the given type /// @@ -2945,7 +2947,7 @@ public static ITypeMap GetTypeMap(Type type) map = (ITypeMap)_typeMaps[type]; if (map == null) { - map = new DefaultTypeMap(type); + map = _defaultTypeMapFactory(type); _typeMaps[type] = map; } } @@ -2953,6 +2955,17 @@ public static ITypeMap GetTypeMap(Type type) return map; } + private static Func _defaultTypeMapFactory; + + /// + /// Set a custom mapping for all types + /// + /// A function that creates the ITypeMap + public static void SetDefaultTypeMap(Func factory) + { + _defaultTypeMapFactory = factory; + } + // use Hashtable to get free lockless reading private static readonly Hashtable _typeMaps = new Hashtable(); @@ -2965,8 +2978,8 @@ public static void SetTypeMap(Type type, ITypeMap map) { if (type == null) throw new ArgumentNullException("type"); - - if (map == null || map is DefaultTypeMap) + + if (map == null) { lock (_typeMaps) { @@ -4352,7 +4365,7 @@ public ParameterInfo Parameter /// /// Represents default type mapping strategy used by Dapper /// - sealed partial class DefaultTypeMap : SqlMapper.ITypeMap + partial class DefaultTypeMap : SqlMapper.ITypeMap { private readonly List _fields; private readonly List _properties; @@ -4404,7 +4417,7 @@ internal static List GetSettableFields(Type t) /// DataReader column names /// DataReader column types /// Matching constructor or default one - public ConstructorInfo FindConstructor(string[] names, Type[] types) + public virtual ConstructorInfo FindConstructor(string[] names, Type[] types) { var constructors = _type.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (ConstructorInfo ctor in constructors.OrderBy(c => c.IsPublic ? 0 : (c.IsPrivate ? 2 : 1)).ThenBy(c => c.GetParameters().Length)) @@ -4443,7 +4456,7 @@ public ConstructorInfo FindConstructor(string[] names, Type[] types) /// Constructor to resolve /// DataReader column name /// Mapping implementation - public SqlMapper.IMemberMap GetConstructorParameter(ConstructorInfo constructor, string columnName) + public virtual SqlMapper.IMemberMap GetConstructorParameter(ConstructorInfo constructor, string columnName) { var parameters = constructor.GetParameters(); @@ -4455,7 +4468,7 @@ public SqlMapper.IMemberMap GetConstructorParameter(ConstructorInfo constructor, /// /// DataReader column name /// Mapping implementation - public SqlMapper.IMemberMap GetMember(string columnName) + public virtual SqlMapper.IMemberMap GetMember(string columnName) { var property = _properties.FirstOrDefault(p => string.Equals(p.Name, columnName, StringComparison.Ordinal)) ?? _properties.FirstOrDefault(p => string.Equals(p.Name, columnName, StringComparison.OrdinalIgnoreCase));