From 43faddb14d7ac0942e3a34e662d29cbe10b5f680 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20=C5=A0ef=C4=8D=C3=ADk?= Date: Wed, 22 May 2019 13:26:46 +0200 Subject: [PATCH 1/6] Replaced Reflection with Dynamic methods in DbSet added items. --- src/Query/DbSet.cs | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/Query/DbSet.cs b/src/Query/DbSet.cs index baa3159..a809bb1 100644 --- a/src/Query/DbSet.cs +++ b/src/Query/DbSet.cs @@ -10,6 +10,9 @@ using System.Data; using System.Data.Common; using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Reflection.Emit; using System.Threading.Tasks; namespace Kros.KORM.Query @@ -280,6 +283,8 @@ private void PrepareCommand(IDbCommand command) } } + private delegate void SetIdentityPrimaryKeyDelegate(T item, object id); + private async Task CommitChangesAddedItemsAsync(HashSet items, bool useAsync) { if (items?.Count > 0) @@ -296,7 +301,30 @@ private async Task CommitChangesAddedItemsAsync(HashSet items, bool useAsync) if (hasIdentity) { var id = await ExecuteScalarAsync(command, useAsync); - _tableInfo.IdentityPrimaryKey.SetValue(item, id); + //_tableInfo.IdentityPrimaryKey.SetValue(item, id); + + // ************ + var dynamicMethodArgs = new Type[] { typeof(T), typeof(object) }; + var dynamicMethod = new DynamicMethod("IdentityPrimaryKey_SetValue", typeof(void), dynamicMethodArgs); + ILGenerator ilGenerator = dynamicMethod.GetILGenerator(); + + ilGenerator.Emit(OpCodes.Ldarg_0); + ilGenerator.Emit(OpCodes.Ldarg_1); + + MethodInfo fnConvertMethod = typeof(System.Convert).GetMethod( + $"To{_tableInfo.IdentityPrimaryKey.PropertyInfo.PropertyType.Name}", new Type[] { typeof(object) }); + + ilGenerator.Emit(OpCodes.Call, fnConvertMethod); + + MethodInfo fnGetIdentity = typeof(T).GetProperty( + _tableInfo.IdentityPrimaryKey.Name, BindingFlags.Public | BindingFlags.Instance).GetSetMethod(); + + ilGenerator.Emit(OpCodes.Callvirt, fnGetIdentity); + ilGenerator.Emit(OpCodes.Ret); + + var invoke = (SetIdentityPrimaryKeyDelegate)dynamicMethod.CreateDelegate(typeof(SetIdentityPrimaryKeyDelegate)); + invoke(item, id); + // ************ } else { From 976b9767d356187a7dec8e96b4b1307bb80ae5b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20=C5=A0ef=C4=8D=C3=ADk?= Date: Wed, 22 May 2019 15:56:31 +0200 Subject: [PATCH 2/6] Refactor. --- src/Query/DbSet.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Query/DbSet.cs b/src/Query/DbSet.cs index a809bb1..79d6a33 100644 --- a/src/Query/DbSet.cs +++ b/src/Query/DbSet.cs @@ -10,7 +10,6 @@ using System.Data; using System.Data.Common; using System.Linq; -using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Threading.Tasks; @@ -283,7 +282,7 @@ private void PrepareCommand(IDbCommand command) } } - private delegate void SetIdentityPrimaryKeyDelegate(T item, object id); + private delegate void _setIdentityPrimaryKeyDelegate(T item, object id); private async Task CommitChangesAddedItemsAsync(HashSet items, bool useAsync) { @@ -311,7 +310,7 @@ private async Task CommitChangesAddedItemsAsync(HashSet items, bool useAsync) ilGenerator.Emit(OpCodes.Ldarg_0); ilGenerator.Emit(OpCodes.Ldarg_1); - MethodInfo fnConvertMethod = typeof(System.Convert).GetMethod( + MethodInfo fnConvertMethod = typeof(Convert).GetMethod( $"To{_tableInfo.IdentityPrimaryKey.PropertyInfo.PropertyType.Name}", new Type[] { typeof(object) }); ilGenerator.Emit(OpCodes.Call, fnConvertMethod); @@ -322,7 +321,7 @@ private async Task CommitChangesAddedItemsAsync(HashSet items, bool useAsync) ilGenerator.Emit(OpCodes.Callvirt, fnGetIdentity); ilGenerator.Emit(OpCodes.Ret); - var invoke = (SetIdentityPrimaryKeyDelegate)dynamicMethod.CreateDelegate(typeof(SetIdentityPrimaryKeyDelegate)); + var invoke = dynamicMethod.CreateDelegate(typeof(_setIdentityPrimaryKeyDelegate)) as _setIdentityPrimaryKeyDelegate; invoke(item, id); // ************ } From 922db7e9fea3ab6d1894362a75239cff14545840 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20=C5=A0ef=C4=8D=C3=ADk?= Date: Wed, 22 May 2019 15:56:51 +0200 Subject: [PATCH 3/6] Replaced reflection with dynamic methods in command generator. --- src/CommandGenerator/CommandGenerator.cs | 31 +++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/CommandGenerator/CommandGenerator.cs b/src/CommandGenerator/CommandGenerator.cs index 98a6284..5f03959 100644 --- a/src/CommandGenerator/CommandGenerator.cs +++ b/src/CommandGenerator/CommandGenerator.cs @@ -8,6 +8,8 @@ using System.Collections.Generic; using System.Data.Common; using System.Linq; +using System.Reflection; +using System.Reflection.Emit; using System.Text; namespace Kros.KORM.CommandGenerator @@ -277,10 +279,37 @@ private void AddParametersToCommand(DbCommand cmd, IEnumerable colum } } + private delegate object _getColumnValueDelegate(T item); + /// public object GetColumnValue(ColumnInfo columnInfo, T item) { - var value = columnInfo.PropertyInfo.GetValue(item, null); + //var temp = columnInfo.PropertyInfo.GetValue(item, null); + + //***************** + var dynamicMethodArgs = new Type[] { typeof(T) }; + var dynamicMethod = new DynamicMethod("GetColumnValue", typeof(object), dynamicMethodArgs); + ILGenerator ilGenerator = dynamicMethod.GetILGenerator(); + + ilGenerator.Emit(OpCodes.Ldarg_0); + + MethodInfo fnGetValue = typeof(T).GetProperty( + columnInfo.PropertyInfo.Name, BindingFlags.Public | BindingFlags.Instance).GetGetMethod(); + + ilGenerator.Emit(OpCodes.Callvirt, fnGetValue); + + if (columnInfo.PropertyInfo.PropertyType.IsValueType) + { + ilGenerator.Emit(OpCodes.Box, columnInfo.PropertyInfo.PropertyType); + } + + ilGenerator.Emit(OpCodes.Ret); + + var invoke = dynamicMethod.CreateDelegate(typeof(_getColumnValueDelegate)) as _getColumnValueDelegate; + var value = invoke(item); + + //***************** + if (value != null) { var converter = ConverterHelper.GetConverter(columnInfo, value.GetType()); From a2a645df8392e468210c8ef521643ed67227918e Mon Sep 17 00:00:00 2001 From: LukasSefcik Date: Thu, 23 May 2019 21:33:48 +0200 Subject: [PATCH 4/6] Unboxing and small refactor. --- src/CommandGenerator/CommandGenerator.cs | 8 +------- src/Query/DbSet.cs | 15 +++++---------- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/src/CommandGenerator/CommandGenerator.cs b/src/CommandGenerator/CommandGenerator.cs index 5f03959..6573fce 100644 --- a/src/CommandGenerator/CommandGenerator.cs +++ b/src/CommandGenerator/CommandGenerator.cs @@ -39,6 +39,7 @@ internal class CommandGenerator : ICommandGenerator private List _columnsInfo = null; private int _maxParametersForDeleteCommandsInPart = DEFAULT_MAX_PARAMETERS_FOR_DELETE_COMMANDS_IN_PART; private Lazy _outputStatement; + private delegate object _getColumnValueDelegate(T item); #endregion @@ -279,14 +280,9 @@ private void AddParametersToCommand(DbCommand cmd, IEnumerable colum } } - private delegate object _getColumnValueDelegate(T item); - /// public object GetColumnValue(ColumnInfo columnInfo, T item) { - //var temp = columnInfo.PropertyInfo.GetValue(item, null); - - //***************** var dynamicMethodArgs = new Type[] { typeof(T) }; var dynamicMethod = new DynamicMethod("GetColumnValue", typeof(object), dynamicMethodArgs); ILGenerator ilGenerator = dynamicMethod.GetILGenerator(); @@ -308,8 +304,6 @@ public object GetColumnValue(ColumnInfo columnInfo, T item) var invoke = dynamicMethod.CreateDelegate(typeof(_getColumnValueDelegate)) as _getColumnValueDelegate; var value = invoke(item); - //***************** - if (value != null) { var converter = ConverterHelper.GetConverter(columnInfo, value.GetType()); diff --git a/src/Query/DbSet.cs b/src/Query/DbSet.cs index 79d6a33..bee1eda 100644 --- a/src/Query/DbSet.cs +++ b/src/Query/DbSet.cs @@ -31,6 +31,7 @@ public class DbSet : IDbSet private HashSet _editedItems = new HashSet(); private HashSet _deletedItems = new HashSet(); private readonly TableInfo _tableInfo; + private delegate void _setIdentityPrimaryKeyDelegate(T item, object id); #endregion @@ -282,8 +283,6 @@ private void PrepareCommand(IDbCommand command) } } - private delegate void _setIdentityPrimaryKeyDelegate(T item, object id); - private async Task CommitChangesAddedItemsAsync(HashSet items, bool useAsync) { if (items?.Count > 0) @@ -300,9 +299,6 @@ private async Task CommitChangesAddedItemsAsync(HashSet items, bool useAsync) if (hasIdentity) { var id = await ExecuteScalarAsync(command, useAsync); - //_tableInfo.IdentityPrimaryKey.SetValue(item, id); - - // ************ var dynamicMethodArgs = new Type[] { typeof(T), typeof(object) }; var dynamicMethod = new DynamicMethod("IdentityPrimaryKey_SetValue", typeof(void), dynamicMethodArgs); ILGenerator ilGenerator = dynamicMethod.GetILGenerator(); @@ -310,10 +306,10 @@ private async Task CommitChangesAddedItemsAsync(HashSet items, bool useAsync) ilGenerator.Emit(OpCodes.Ldarg_0); ilGenerator.Emit(OpCodes.Ldarg_1); - MethodInfo fnConvertMethod = typeof(Convert).GetMethod( - $"To{_tableInfo.IdentityPrimaryKey.PropertyInfo.PropertyType.Name}", new Type[] { typeof(object) }); - - ilGenerator.Emit(OpCodes.Call, fnConvertMethod); + if (_tableInfo.IdentityPrimaryKey.PropertyInfo.PropertyType.IsValueType) + { + ilGenerator.Emit(OpCodes.Unbox_Any, _tableInfo.IdentityPrimaryKey.PropertyInfo.PropertyType); + } MethodInfo fnGetIdentity = typeof(T).GetProperty( _tableInfo.IdentityPrimaryKey.Name, BindingFlags.Public | BindingFlags.Instance).GetSetMethod(); @@ -323,7 +319,6 @@ private async Task CommitChangesAddedItemsAsync(HashSet items, bool useAsync) var invoke = dynamicMethod.CreateDelegate(typeof(_setIdentityPrimaryKeyDelegate)) as _setIdentityPrimaryKeyDelegate; invoke(item, id); - // ************ } else { From 388ed35e82061f84405f90c832e642c7e001b674 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20=C5=A0ef=C4=8D=C3=ADk?= Date: Fri, 24 May 2019 10:23:48 +0200 Subject: [PATCH 5/6] PR comments. --- src/CommandGenerator/CommandGenerator.cs | 64 +++++++++++++--------- src/Query/DbSet.cs | 68 ++++++++++++++---------- 2 files changed, 80 insertions(+), 52 deletions(-) diff --git a/src/CommandGenerator/CommandGenerator.cs b/src/CommandGenerator/CommandGenerator.cs index 6573fce..1589627 100644 --- a/src/CommandGenerator/CommandGenerator.cs +++ b/src/CommandGenerator/CommandGenerator.cs @@ -1,4 +1,5 @@ -using Kros.KORM.Converter; +using Kros.Caching; +using Kros.KORM.Converter; using Kros.KORM.Metadata; using Kros.KORM.Properties; using Kros.KORM.Query; @@ -33,12 +34,13 @@ internal class CommandGenerator : ICommandGenerator #region Private Fields - private TableInfo _tableInfo; - private KORM.Query.IQueryProvider _provider; - private IQueryBase _query; + private readonly TableInfo _tableInfo; + private readonly KORM.Query.IQueryProvider _provider; + private readonly IQueryBase _query; private List _columnsInfo = null; private int _maxParametersForDeleteCommandsInPart = DEFAULT_MAX_PARAMETERS_FOR_DELETE_COMMANDS_IN_PART; - private Lazy _outputStatement; + private readonly Lazy _outputStatement; + private readonly ICache _delegatesCache = new Cache(); private delegate object _getColumnValueDelegate(T item); #endregion @@ -283,26 +285,8 @@ private void AddParametersToCommand(DbCommand cmd, IEnumerable colum /// public object GetColumnValue(ColumnInfo columnInfo, T item) { - var dynamicMethodArgs = new Type[] { typeof(T) }; - var dynamicMethod = new DynamicMethod("GetColumnValue", typeof(object), dynamicMethodArgs); - ILGenerator ilGenerator = dynamicMethod.GetILGenerator(); - - ilGenerator.Emit(OpCodes.Ldarg_0); - - MethodInfo fnGetValue = typeof(T).GetProperty( - columnInfo.PropertyInfo.Name, BindingFlags.Public | BindingFlags.Instance).GetGetMethod(); - - ilGenerator.Emit(OpCodes.Callvirt, fnGetValue); - - if (columnInfo.PropertyInfo.PropertyType.IsValueType) - { - ilGenerator.Emit(OpCodes.Box, columnInfo.PropertyInfo.PropertyType); - } - - ilGenerator.Emit(OpCodes.Ret); - - var invoke = dynamicMethod.CreateDelegate(typeof(_getColumnValueDelegate)) as _getColumnValueDelegate; - var value = invoke(item); + _getColumnValueDelegate invokeDelegate = GetDelegate(item, columnInfo); + var value = invokeDelegate(item); if (value != null) { @@ -391,6 +375,36 @@ private string GetDeleteCommandText(IEnumerable columns) return string.Format(DELETE_QUERY_BASE, _tableInfo.Name, paramWherePart.ToString()); } + private _getColumnValueDelegate GetDelegate(T item, ColumnInfo columnInfo) + { + var key = columnInfo.Name.ToUpper().GetHashCode() ^ item.GetHashCode(); + + return _delegatesCache.Get(key, () => CreateDelegate(columnInfo)) as _getColumnValueDelegate; + } + + private _getColumnValueDelegate CreateDelegate(ColumnInfo columnInfo) + { + var dynamicMethodArgs = new Type[] { typeof(T) }; + var dynamicMethod = new DynamicMethod("GetColumnValue", typeof(object), dynamicMethodArgs); + ILGenerator ilGenerator = dynamicMethod.GetILGenerator(); + + ilGenerator.Emit(OpCodes.Ldarg_0); + + MethodInfo fnGetValue = typeof(T).GetProperty( + columnInfo.PropertyInfo.Name, BindingFlags.Public | BindingFlags.Instance).GetGetMethod(); + + ilGenerator.Emit(OpCodes.Callvirt, fnGetValue); + + if (columnInfo.PropertyInfo.PropertyType.IsValueType) + { + ilGenerator.Emit(OpCodes.Box, columnInfo.PropertyInfo.PropertyType); + } + + ilGenerator.Emit(OpCodes.Ret); + + return dynamicMethod.CreateDelegate(typeof(_getColumnValueDelegate)) as _getColumnValueDelegate; + } + #endregion } } diff --git a/src/Query/DbSet.cs b/src/Query/DbSet.cs index bee1eda..ea24439 100644 --- a/src/Query/DbSet.cs +++ b/src/Query/DbSet.cs @@ -1,4 +1,5 @@ -using Kros.KORM.CommandGenerator; +using Kros.Caching; +using Kros.KORM.CommandGenerator; using Kros.KORM.Data; using Kros.KORM.Exceptions; using Kros.KORM.Metadata; @@ -24,13 +25,14 @@ public class DbSet : IDbSet { #region Private fields - private ICommandGenerator _commandGenerator; - private IQueryProvider _provider; - private IQueryBase _query; - private HashSet _addedItems = new HashSet(); - private HashSet _editedItems = new HashSet(); - private HashSet _deletedItems = new HashSet(); + private readonly ICommandGenerator _commandGenerator; + private readonly IQueryProvider _provider; + private readonly IQueryBase _query; + private readonly HashSet _addedItems = new HashSet(); + private readonly HashSet _editedItems = new HashSet(); + private readonly HashSet _deletedItems = new HashSet(); private readonly TableInfo _tableInfo; + private readonly ICache _delegatesCache = new Cache(); private delegate void _setIdentityPrimaryKeyDelegate(T item, object id); #endregion @@ -299,26 +301,8 @@ private async Task CommitChangesAddedItemsAsync(HashSet items, bool useAsync) if (hasIdentity) { var id = await ExecuteScalarAsync(command, useAsync); - var dynamicMethodArgs = new Type[] { typeof(T), typeof(object) }; - var dynamicMethod = new DynamicMethod("IdentityPrimaryKey_SetValue", typeof(void), dynamicMethodArgs); - ILGenerator ilGenerator = dynamicMethod.GetILGenerator(); - - ilGenerator.Emit(OpCodes.Ldarg_0); - ilGenerator.Emit(OpCodes.Ldarg_1); - - if (_tableInfo.IdentityPrimaryKey.PropertyInfo.PropertyType.IsValueType) - { - ilGenerator.Emit(OpCodes.Unbox_Any, _tableInfo.IdentityPrimaryKey.PropertyInfo.PropertyType); - } - - MethodInfo fnGetIdentity = typeof(T).GetProperty( - _tableInfo.IdentityPrimaryKey.Name, BindingFlags.Public | BindingFlags.Instance).GetSetMethod(); - - ilGenerator.Emit(OpCodes.Callvirt, fnGetIdentity); - ilGenerator.Emit(OpCodes.Ret); - - var invoke = dynamicMethod.CreateDelegate(typeof(_setIdentityPrimaryKeyDelegate)) as _setIdentityPrimaryKeyDelegate; - invoke(item, id); + _setIdentityPrimaryKeyDelegate invokeDelegate = GetDelegate(item, _tableInfo.IdentityPrimaryKey); + invokeDelegate(item, id); } else { @@ -490,6 +474,36 @@ private async Task BulkUpdateCoreAsync( } } + private _setIdentityPrimaryKeyDelegate GetDelegate(T item, ColumnInfo columnInfo) + { + var key = columnInfo.Name.ToUpper().GetHashCode() ^ item.GetHashCode(); + + return _delegatesCache.Get(key, () => CreateDelegate(columnInfo)) as _setIdentityPrimaryKeyDelegate; + } + + private _setIdentityPrimaryKeyDelegate CreateDelegate(ColumnInfo columnInfo) + { + var dynamicMethodArgs = new Type[] { typeof(T), typeof(object) }; + var dynamicMethod = new DynamicMethod("IdentityPrimaryKey_SetValue", typeof(void), dynamicMethodArgs); + ILGenerator ilGenerator = dynamicMethod.GetILGenerator(); + + ilGenerator.Emit(OpCodes.Ldarg_0); + ilGenerator.Emit(OpCodes.Ldarg_1); + + if (columnInfo.PropertyInfo.PropertyType.IsValueType) + { + ilGenerator.Emit(OpCodes.Unbox_Any, columnInfo.PropertyInfo.PropertyType); + } + + MethodInfo fnGetIdentity = typeof(T).GetProperty( + columnInfo.Name, BindingFlags.Public | BindingFlags.Instance).GetSetMethod(); + + ilGenerator.Emit(OpCodes.Callvirt, fnGetIdentity); + ilGenerator.Emit(OpCodes.Ret); + + return dynamicMethod.CreateDelegate(typeof(_setIdentityPrimaryKeyDelegate)) as _setIdentityPrimaryKeyDelegate; + } + #endregion #region IEnumerator From 7b8a233a5a388aeba371e6f322e69eea1100202a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20=C5=A0ef=C4=8D=C3=ADk?= Date: Fri, 24 May 2019 13:30:30 +0200 Subject: [PATCH 6/6] Bug fix creating cache. --- src/CommandGenerator/CommandGenerator.cs | 14 +++++++------- src/Query/DbSet.cs | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/CommandGenerator/CommandGenerator.cs b/src/CommandGenerator/CommandGenerator.cs index 1589627..ac13944 100644 --- a/src/CommandGenerator/CommandGenerator.cs +++ b/src/CommandGenerator/CommandGenerator.cs @@ -41,7 +41,7 @@ internal class CommandGenerator : ICommandGenerator private int _maxParametersForDeleteCommandsInPart = DEFAULT_MAX_PARAMETERS_FOR_DELETE_COMMANDS_IN_PART; private readonly Lazy _outputStatement; private readonly ICache _delegatesCache = new Cache(); - private delegate object _getColumnValueDelegate(T item); + private delegate object GetColumnValueDelegate(T item); #endregion @@ -285,7 +285,7 @@ private void AddParametersToCommand(DbCommand cmd, IEnumerable colum /// public object GetColumnValue(ColumnInfo columnInfo, T item) { - _getColumnValueDelegate invokeDelegate = GetDelegate(item, columnInfo); + GetColumnValueDelegate invokeDelegate = GetDelegate(item, columnInfo); var value = invokeDelegate(item); if (value != null) @@ -375,14 +375,14 @@ private string GetDeleteCommandText(IEnumerable columns) return string.Format(DELETE_QUERY_BASE, _tableInfo.Name, paramWherePart.ToString()); } - private _getColumnValueDelegate GetDelegate(T item, ColumnInfo columnInfo) + private GetColumnValueDelegate GetDelegate(T item, ColumnInfo columnInfo) { - var key = columnInfo.Name.ToUpper().GetHashCode() ^ item.GetHashCode(); + var key = $"{columnInfo.Name}-{typeof(T).FullName}".GetHashCode(); - return _delegatesCache.Get(key, () => CreateDelegate(columnInfo)) as _getColumnValueDelegate; + return _delegatesCache.Get(key, () => CreateDelegate(columnInfo)) as GetColumnValueDelegate; } - private _getColumnValueDelegate CreateDelegate(ColumnInfo columnInfo) + private GetColumnValueDelegate CreateDelegate(ColumnInfo columnInfo) { var dynamicMethodArgs = new Type[] { typeof(T) }; var dynamicMethod = new DynamicMethod("GetColumnValue", typeof(object), dynamicMethodArgs); @@ -402,7 +402,7 @@ private _getColumnValueDelegate CreateDelegate(ColumnInfo columnInfo) ilGenerator.Emit(OpCodes.Ret); - return dynamicMethod.CreateDelegate(typeof(_getColumnValueDelegate)) as _getColumnValueDelegate; + return dynamicMethod.CreateDelegate(typeof(GetColumnValueDelegate)) as GetColumnValueDelegate; } #endregion diff --git a/src/Query/DbSet.cs b/src/Query/DbSet.cs index ea24439..db1fbc5 100644 --- a/src/Query/DbSet.cs +++ b/src/Query/DbSet.cs @@ -33,7 +33,7 @@ public class DbSet : IDbSet private readonly HashSet _deletedItems = new HashSet(); private readonly TableInfo _tableInfo; private readonly ICache _delegatesCache = new Cache(); - private delegate void _setIdentityPrimaryKeyDelegate(T item, object id); + private delegate void SetIdentityPrimaryKeyDelegate(T item, object id); #endregion @@ -301,7 +301,7 @@ private async Task CommitChangesAddedItemsAsync(HashSet items, bool useAsync) if (hasIdentity) { var id = await ExecuteScalarAsync(command, useAsync); - _setIdentityPrimaryKeyDelegate invokeDelegate = GetDelegate(item, _tableInfo.IdentityPrimaryKey); + SetIdentityPrimaryKeyDelegate invokeDelegate = GetDelegate(item, _tableInfo.IdentityPrimaryKey); invokeDelegate(item, id); } else @@ -474,14 +474,14 @@ private async Task BulkUpdateCoreAsync( } } - private _setIdentityPrimaryKeyDelegate GetDelegate(T item, ColumnInfo columnInfo) + private SetIdentityPrimaryKeyDelegate GetDelegate(T item, ColumnInfo columnInfo) { - var key = columnInfo.Name.ToUpper().GetHashCode() ^ item.GetHashCode(); + var key = $"{columnInfo.Name}-{typeof(T).FullName}".GetHashCode(); - return _delegatesCache.Get(key, () => CreateDelegate(columnInfo)) as _setIdentityPrimaryKeyDelegate; + return _delegatesCache.Get(key, () => CreateDelegate(columnInfo)) as SetIdentityPrimaryKeyDelegate; } - private _setIdentityPrimaryKeyDelegate CreateDelegate(ColumnInfo columnInfo) + private SetIdentityPrimaryKeyDelegate CreateDelegate(ColumnInfo columnInfo) { var dynamicMethodArgs = new Type[] { typeof(T), typeof(object) }; var dynamicMethod = new DynamicMethod("IdentityPrimaryKey_SetValue", typeof(void), dynamicMethodArgs); @@ -501,7 +501,7 @@ private _setIdentityPrimaryKeyDelegate CreateDelegate(ColumnInfo columnInfo) ilGenerator.Emit(OpCodes.Callvirt, fnGetIdentity); ilGenerator.Emit(OpCodes.Ret); - return dynamicMethod.CreateDelegate(typeof(_setIdentityPrimaryKeyDelegate)) as _setIdentityPrimaryKeyDelegate; + return dynamicMethod.CreateDelegate(typeof(SetIdentityPrimaryKeyDelegate)) as SetIdentityPrimaryKeyDelegate; } #endregion