1818using Xtensive . Sql . Info ;
1919using Xtensive . Sql . Model ;
2020using Xtensive . Tuples ;
21+ using System . Collections . Concurrent ;
22+ using Xtensive . Linq ;
23+ using System . Linq . Expressions ;
24+ using System . Reflection ;
2125
2226namespace Xtensive . Orm . Providers
2327{
@@ -26,13 +30,17 @@ namespace Xtensive.Orm.Providers
2630 /// </summary>
2731 public sealed partial class StorageDriver
2832 {
33+ private static readonly MethodInfo FactoryCreatorMethod = typeof ( StorageDriver ) . GetMethod ( nameof ( NewFactory ) , BindingFlags . Static | BindingFlags . NonPublic ) ;
34+
2935 private readonly DomainConfiguration configuration ;
3036 private readonly SqlDriver underlyingDriver ;
3137 private readonly SqlTranslator translator ;
3238 private readonly TypeMappingRegistry allMappings ;
3339 private readonly bool isLoggingEnabled ;
3440 private readonly bool hasSavepoints ;
3541
42+ private readonly ConcurrentDictionary < Type , Func < IConnectionHandler > > handlerFactoriesCache ;
43+
3644 public ProviderInfo ProviderInfo { get ; private set ; }
3745
3846 public StorageExceptionBuilder ExceptionBuilder { get ; private set ; }
@@ -97,7 +105,7 @@ public DbDataReaderAccessor GetDataReaderAccessor(TupleDescriptor descriptor)
97105 public StorageDriver CreateNew ( Domain domain )
98106 {
99107 ArgumentValidator . EnsureArgumentNotNull ( domain , "domain" ) ;
100- return new StorageDriver ( underlyingDriver , ProviderInfo , domain . Configuration , GetModelProvider ( domain ) ) ;
108+ return new StorageDriver ( underlyingDriver , ProviderInfo , domain . Configuration , GetModelProvider ( domain ) , handlerFactoriesCache ) ;
101109 }
102110
103111 private static DomainModel GetNullModel ( )
@@ -151,14 +159,51 @@ private void FixExtractionResultSqlServerFamily(SqlExtractionResult result)
151159 }
152160 }
153161
162+ private IReadOnlyCollection < IConnectionHandler > CreateHandlersForConnection ( IEnumerable < Type > connectionHandlerTypes )
163+ {
164+ if ( handlerFactoriesCache == null )
165+ return Array . Empty < IConnectionHandler > ( ) ;
166+ var instances = new List < IConnectionHandler > ( handlerFactoriesCache . Count ) ;
167+ foreach ( var type in connectionHandlerTypes ) {
168+ if ( handlerFactoriesCache . TryGetValue ( type , out var factory ) )
169+ instances . Add ( factory ( ) ) ;
170+ }
171+ return instances . ToArray ( ) ;
172+ }
173+
174+ // used on driver creation so it is very first time handlers are created.
175+ // great place to create and cache factories for faster initialization on session opening later
176+ private static IReadOnlyCollection < IConnectionHandler > CreateConnectionHandlers ( IEnumerable < Type > connectionHandlerTypes ,
177+ out ConcurrentDictionary < Type , Func < IConnectionHandler > > factories )
178+ {
179+ var instances = new List < IConnectionHandler > ( ) ;
180+ factories = new ConcurrentDictionary < Type , Func < IConnectionHandler > > ( ) ;
181+ foreach ( var item in connectionHandlerTypes ) {
182+ var handlerFactory = ( Func < IConnectionHandler > ) FactoryCreatorMethod . MakeGenericMethod ( item ) . Invoke ( null , null ) ;
183+ instances . Add ( handlerFactory ( ) ) ;
184+ factories [ item ] = handlerFactory ;
185+ }
186+ if ( factories . Count == 0 )
187+ factories = null ;
188+ return instances . ToArray ( ) ;
189+ }
190+
191+ private static Func < IConnectionHandler > NewFactory < T > ( ) where T : IConnectionHandler
192+ {
193+ return FastExpression . Lambda < Func < IConnectionHandler > > (
194+ Expression . Convert ( Expression . New ( typeof ( T ) ) , typeof ( IConnectionHandler ) ) )
195+ . Compile ( ) ;
196+ }
197+
154198 // Constructors
155199
156200 public static StorageDriver Create ( SqlDriverFactory driverFactory , DomainConfiguration configuration )
157201 {
158202 ArgumentValidator . EnsureArgumentNotNull ( driverFactory , nameof ( driverFactory ) ) ;
159203 ArgumentValidator . EnsureArgumentNotNull ( configuration , nameof ( configuration ) ) ;
160204
161- var driverConfiguration = new SqlDriverConfiguration {
205+ var handlers = CreateConnectionHandlers ( configuration . Types . ConnectionHandlers , out var factories ) ;
206+ var driverConfiguration = new SqlDriverConfiguration ( handlers ) {
162207 ForcedServerVersion = configuration . ForcedServerVersion ,
163208 ConnectionInitializationSql = configuration . ConnectionInitializationSql ,
164209 EnsureConnectionIsAlive = configuration . EnsureConnectionIsAlive ,
@@ -167,7 +212,7 @@ public static StorageDriver Create(SqlDriverFactory driverFactory, DomainConfigu
167212 var driver = driverFactory . GetDriver ( configuration . ConnectionInfo , driverConfiguration ) ;
168213 var providerInfo = ProviderInfoBuilder . Build ( configuration . ConnectionInfo . Provider , driver ) ;
169214
170- return new StorageDriver ( driver , providerInfo , configuration , GetNullModel ) ;
215+ return new StorageDriver ( driver , providerInfo , configuration , GetNullModel , factories ) ;
171216 }
172217
173218 public static async Task < StorageDriver > CreateAsync (
@@ -176,7 +221,8 @@ public static async Task<StorageDriver> CreateAsync(
176221 ArgumentValidator . EnsureArgumentNotNull ( driverFactory , nameof ( driverFactory ) ) ;
177222 ArgumentValidator . EnsureArgumentNotNull ( configuration , nameof ( configuration ) ) ;
178223
179- var driverConfiguration = new SqlDriverConfiguration {
224+ var handlers = CreateConnectionHandlers ( configuration . Types . ConnectionHandlers , out var factories ) ;
225+ var driverConfiguration = new SqlDriverConfiguration ( handlers ) {
180226 ForcedServerVersion = configuration . ForcedServerVersion ,
181227 ConnectionInitializationSql = configuration . ConnectionInitializationSql ,
182228 EnsureConnectionIsAlive = configuration . EnsureConnectionIsAlive ,
@@ -186,11 +232,14 @@ public static async Task<StorageDriver> CreateAsync(
186232 . ConfigureAwait ( false ) ;
187233 var providerInfo = ProviderInfoBuilder . Build ( configuration . ConnectionInfo . Provider , driver ) ;
188234
189- return new StorageDriver ( driver , providerInfo , configuration , GetNullModel ) ;
235+ return new StorageDriver ( driver , providerInfo , configuration , GetNullModel , factories ) ;
190236 }
191237
192- private StorageDriver (
193- SqlDriver driver , ProviderInfo providerInfo , DomainConfiguration configuration , Func < DomainModel > modelProvider )
238+ private StorageDriver ( SqlDriver driver ,
239+ ProviderInfo providerInfo ,
240+ DomainConfiguration configuration ,
241+ Func < DomainModel > modelProvider ,
242+ ConcurrentDictionary < Type , Func < IConnectionHandler > > factoryCache )
194243 {
195244 underlyingDriver = driver ;
196245 ProviderInfo = providerInfo ;
@@ -201,6 +250,7 @@ private StorageDriver(
201250 hasSavepoints = underlyingDriver . ServerInfo . ServerFeatures . Supports ( ServerFeatures . Savepoints ) ;
202251 isLoggingEnabled = SqlLog . IsLogged ( LogLevel . Info ) ; // Just to cache this value
203252 ServerInfo = underlyingDriver . ServerInfo ;
253+ handlerFactoriesCache = factoryCache ;
204254 }
205255 }
206256}
0 commit comments