Skip to content

Commit 7046394

Browse files
committed
NH-3856 - Improve performance of SqlClientSqlCommandSet
Move reflection to the static constructor, so we do not need to waste time building delegates on instance creation.
1 parent e6245b1 commit 7046394

File tree

1 file changed

+29
-27
lines changed

1 file changed

+29
-27
lines changed

src/NHibernate/AdoNet/SqlClientSqlCommandSet.cs

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
using System.Data.SqlClient;
33
using System.Diagnostics;
44
using System.Reflection;
5+
using NHibernate.Util;
56

67
namespace NHibernate.AdoNet
78
{
8-
using Action = System.Action;
99
using SqlCommand = System.Data.SqlClient.SqlCommand;
1010

1111
/// <summary>
12-
/// Expose the batch functionality in ADO.Net 2.0
12+
/// Expose the batch functionality in ADO.Net 4.0
1313
/// Microsoft in its wisdom decided to make my life hard and mark it internal.
1414
/// Through the use of Reflection and some delegates magic, I opened up the functionality.
1515
///
@@ -18,35 +18,37 @@ namespace NHibernate.AdoNet
1818
public class SqlClientSqlCommandSet : IDisposable
1919
{
2020
private static readonly System.Type sqlCmdSetType;
21+
private static readonly Action<object, SqlConnection> connectionSetter;
22+
private static readonly Action<object, SqlTransaction> transactionSetter;
23+
private static readonly Action<object, int> commandTimeoutSetter;
24+
private static readonly Func<object, SqlConnection> connectionGetter;
25+
private static readonly Func<object, SqlCommand> batchCommandGetter;
26+
private static readonly Action<object, SqlCommand> doAppend;
27+
private static readonly Func<object, int> doExecuteNonQuery;
28+
private static readonly Action<object> doDispose;
29+
2130
private readonly object instance;
22-
private readonly Action<SqlConnection> connectionSetter;
23-
private readonly Action<SqlTransaction> transactionSetter;
24-
private readonly Action<int> commandTimeoutSetter;
25-
private readonly Func<SqlConnection> connectionGetter;
26-
private readonly Func<SqlCommand> commandGetter;
27-
private readonly Action<SqlCommand> doAppend;
28-
private readonly Func<int> doExecuteNonQuery;
29-
private readonly Action doDispose;
3031
private int countOfCommands;
3132

3233
static SqlClientSqlCommandSet()
3334
{
34-
var sysData = Assembly.Load("System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
35+
var sysData = Assembly.Load("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
3536
sqlCmdSetType = sysData.GetType("System.Data.SqlClient.SqlCommandSet");
3637
Debug.Assert(sqlCmdSetType != null, "Could not find SqlCommandSet!");
38+
39+
connectionSetter = DelegateHelper.BuildPropertySetter<SqlConnection>(sqlCmdSetType, "Connection");
40+
connectionGetter = DelegateHelper.BuildPropertyGetter<SqlConnection>(sqlCmdSetType, "Connection");
41+
transactionSetter = DelegateHelper.BuildPropertySetter<SqlTransaction>(sqlCmdSetType, "Transaction");
42+
commandTimeoutSetter = DelegateHelper.BuildPropertySetter<int>(sqlCmdSetType, "CommandTimeout");
43+
batchCommandGetter = DelegateHelper.BuildPropertyGetter<SqlCommand>(sqlCmdSetType, "BatchCommand");
44+
doAppend = DelegateHelper.BuildAction<SqlCommand>(sqlCmdSetType, "Append");
45+
doExecuteNonQuery = DelegateHelper.BuildFunc<int>(sqlCmdSetType, "ExecuteNonQuery");
46+
doDispose = DelegateHelper.BuildAction(sqlCmdSetType, "Dispose");
3747
}
3848

3949
public SqlClientSqlCommandSet()
4050
{
4151
instance = Activator.CreateInstance(sqlCmdSetType, true);
42-
connectionSetter = (Action<SqlConnection>) Delegate.CreateDelegate(typeof (Action<SqlConnection>), instance, "set_Connection");
43-
transactionSetter = (Action<SqlTransaction>) Delegate.CreateDelegate(typeof (Action<SqlTransaction>), instance, "set_Transaction");
44-
commandTimeoutSetter = (Action<int>) Delegate.CreateDelegate(typeof (Action<int>), instance, "set_CommandTimeout");
45-
connectionGetter = (Func<SqlConnection>) Delegate.CreateDelegate(typeof (Func<SqlConnection>), instance, "get_Connection");
46-
commandGetter = (Func<SqlCommand>) Delegate.CreateDelegate(typeof (Func<SqlCommand>), instance, "get_BatchCommand");
47-
doAppend = (Action<SqlCommand>) Delegate.CreateDelegate(typeof (Action<SqlCommand>), instance, "Append");
48-
doExecuteNonQuery = (Func<int>) Delegate.CreateDelegate(typeof (Func<int>), instance, "ExecuteNonQuery");
49-
doDispose = (Action) Delegate.CreateDelegate(typeof (Action), instance, "Dispose");
5052
}
5153

5254
/// <summary>
@@ -56,7 +58,7 @@ public SqlClientSqlCommandSet()
5658
public void Append(SqlCommand command)
5759
{
5860
AssertHasParameters(command);
59-
doAppend(command);
61+
doAppend(instance, command);
6062
countOfCommands++;
6163
}
6264

@@ -79,7 +81,7 @@ private static void AssertHasParameters(SqlCommand command)
7981
/// </summary>
8082
public SqlCommand BatchCommand
8183
{
82-
get { return commandGetter(); }
84+
get { return batchCommandGetter(instance); }
8385
}
8486

8587
/// <summary>
@@ -104,23 +106,23 @@ public int ExecuteNonQuery()
104106

105107
if (CountOfCommands == 0)
106108
return 0;
107-
return doExecuteNonQuery();
109+
return doExecuteNonQuery(instance);
108110
}
109111

110112
public SqlConnection Connection
111113
{
112-
get { return connectionGetter(); }
113-
set { connectionSetter(value); }
114+
get { return connectionGetter(instance); }
115+
set { connectionSetter(instance, value); }
114116
}
115117

116118
public SqlTransaction Transaction
117119
{
118-
set { transactionSetter(value); }
120+
set { transactionSetter(instance, value); }
119121
}
120122

121123
public int CommandTimeout
122124
{
123-
set { commandTimeoutSetter(value); }
125+
set { commandTimeoutSetter(instance, value); }
124126
}
125127

126128
///<summary>
@@ -129,7 +131,7 @@ public int CommandTimeout
129131
///<filterpriority>2</filterpriority>
130132
public void Dispose()
131133
{
132-
doDispose();
134+
doDispose(instance);
133135
}
134136
}
135137
}

0 commit comments

Comments
 (0)