internal static Func <IDataRecord, T> ProvideLoader <T>(IDataRecord reader, out QueryTalkException exception) { exception = null; object loader; Type type = typeof(T); Loader.ColumnInfo[] columns; Cache.LoaderCacheKey cacheKey = Cache.LoaderCacheKey.Default; Cache.LoaderCacheValue cacheValue; var loaderType = Cache.GetLoaderType(type); int hash = 0; // check cache if (Admin.IsLoaderCachingOn) { hash = GetLoaderHash(reader); cacheKey = new Cache.LoaderCacheKey(hash, loaderType, type); if (Cache.TryGetLoaderCache <T>(reader, cacheKey, out cacheValue)) { return((Func <IDataRecord, T>)cacheValue.Loader); } } // dynamic loading if (loaderType == Cache.LoaderType.Dynamic) { columns = ReflectReader(reader, out exception); if (exception != null) { exception.Arguments += String.Format("{0} table = {1}", Environment.NewLine, type); return(null); } TryThrowInvalidDataClassException(null, columns); Type dynamicType = Loader.EmitTable(columns, Guid.NewGuid()); loader = Loader.EmitRowLoaderDynamic(columns, dynamicType); } // Row else if (loaderType == Cache.LoaderType.Row) { columns = ReflectRow(type, reader); TryThrowInvalidDataClassException(type, columns); loader = Loader.EmitRowLoader <T>(columns); } // regular data class else { columns = ReflectClass(type, reader); TryThrowInvalidDataClassException(type, columns); loader = Loader.EmitRowLoader <T>(columns); } // cache loader if (Admin.IsLoaderCachingOn) { cacheValue = new Cache.LoaderCacheValue(columns, loader); Cache.Loaders.TryAdd(cacheKey, cacheValue); } return((Func <IDataRecord, T>)loader); }
internal static bool TryGetLoaderCache <T>(IDataRecord reader, Cache.LoaderCacheKey cacheKey, out Cache.LoaderCacheValue cacheValue) { if (Cache.Loaders.TryGetValue(cacheKey, out cacheValue)) { try { ((Func <IDataRecord, T>)cacheValue.Loader).Invoke(reader); return(true); } // safe: // The exception is intercepted here only once in order to generate new loader code. // (Very unlikely to happen.) catch { Cache.Loaders.TryRemove(cacheKey, out cacheValue); return(false); } } return(false); }