/// <summary> /// Initializes a new instance of ImmediateNotificationRegister class. /// </summary> /// <param name="context">an instance of DbContext is used to get an ObjectQuery object</param> /// <param name="query">an instance of IQueryable is used to get ObjectQuery object, and then get /// connection string and command string to register SqlDependency nitification. </param> public ImmediateSqlNotificationRegister(IDbContextBase context, IQueryable query, CacheInfo cacheInfo) { Init(context, query, cacheInfo); }
private void Init(IDbContextBase context, IQueryable query, int delayForRetryOnError, CacheInfo cacheInfo) { try { StartMonitor(context); this.iquery = query; // Get the ObjectQuery directly or convert the DbQuery to ObjectQuery. Core.Cmn.Extensions.QueryableExt.GetSqlCommand <TEntity>(context, query, ref connection, ref command); RegisterSqlDependency(); } catch (Exception ex) { try { using (var trace = new Trace.TraceDto()) { trace.TraceKey = "CacheSqlDependency"; trace.Data["CacheName"] = cacheInfo.Name; trace.Data["DateTime"] = DateTime.Now.ToString(); trace.Data["Exception"] = ex.ToString(); trace.Message = $"CacheSql Dependency {cacheInfo.Name} has faced with an exception at {DateTime.Now.ToString()} ..."; trace.Data["State"] = "initialize"; Core.Cmn.AppBase.TraceWriter.SubmitData(trace); } Core.Cmn.AppBase.LogService.Handle(ex, $"Exception on initialize ImmediateNotificationRegister for cache on SqlDependency, the query is {iquery}..."); } catch { } Task.Delay(delayForRetryOnError).Wait(); Init(context, query, delayForRetryOnError + 1000, cacheInfo); } }
public static T MergeFreshDataByOldCache <T>(T oldData, T newData, CacheInfo cacheInfo, bool isQueryableCache, out List <ObjectBase> entitiesForDeletion, out List <ObjectBase> entitiesForAddition, out List <ObjectBase> entitiesForUpdates) { entitiesForDeletion = null; entitiesForAddition = null; entitiesForUpdates = null; var nlst = (newData as IList); T resultList = oldData; if (oldData == null) { resultList = newData; } else { if (!cacheInfo.DisableToSyncDeletedRecord_JustIfEnableToFetchOnlyChangedDataFromDB && !cacheInfo.IsFunctionalCache) { var deletedRecords = CacheConfig.CacheManagementRepository. GetDeletedRecordsByTable(cacheInfo.Repository.Schema + "." + cacheInfo.Repository.TableName, cacheInfo.MaxTimeStampForDeletedRecord, cacheInfo.CacheRefreshingKind != CacheRefreshingKind.SqlDependency); if (deletedRecords.Count > 0) { var maxDeletedRecordItem = (ObjectBase)deletedRecords.OrderByDescending(item => ((ObjectBase)item).TimeStampUnit).First(); var maxTimeStampDeletedRecords = ((ObjectBase)maxDeletedRecordItem).TimeStampUnit; var oldEntityBaseLst = (oldData as IList).Cast <ObjectBase>().ToList(); var oldLst = oldData as IList; entitiesForDeletion = new List <ObjectBase>(); foreach (var record in deletedRecords) { if (nlst != null && nlst.Count > 0) { var newItemToRemove = nlst.Cast <ObjectBase>().FirstOrDefault(item => item.CacheId == record.DeletedEntityId); if (newItemToRemove != null) { nlst.Remove(newItemToRemove); newItemToRemove.IsDeletedForCache = true; } } var itemToRemove = oldEntityBaseLst.FirstOrDefault(item => item.CacheId == record.DeletedEntityId); if (itemToRemove != null) { entitiesForDeletion.Add(itemToRemove); oldLst.Remove(itemToRemove); itemToRemove.IsDeletedForCache = true; foreach (var inf in cacheInfo.InfoAndEntityListForFillingNavigationPropertyDic.ToList()) { List <ObjectBase> entities; /// attention: Added Tolist Here //lock (inf.Value) //{ entities = inf.Value.Where(en => { var thisPropertyValue = en[inf.Key.ThisEntityRefrencePropertyName]; return(thisPropertyValue != null && thisPropertyValue.Equals(itemToRemove[inf.Key.OtherEntityRefrencePropertyName])); }).ToList(); //} //Where(en => en[inf.Key.ThisEntityRefrencePropertyName].Equals(itemToRemove[inf.Key.OtherEntityRefrencePropertyName])).ToList() entities.ForEach((Action <ObjectBase>)((ObjectBase parentEntity) => { object navContainer; if (parentEntity.NavigationPropertyDataDic.TryGetValue(inf.Key.PropertyInfo.Name, out navContainer)) { if (inf.Key.IsEnumerable) { // var navContainer = parentEntity.NavigationPropertyDataDic[inf.Key.PropertyInfo.Name]; var navPropList = navContainer as IList; if (navPropList.Count > 0) { IList newNavProp = Activator.CreateInstance(navContainer.GetType()) as IList; navPropList.Cast <ObjectBase>().ToList().ForEach((ObjectBase entity) => { if (!entity.Equals(itemToRemove)) { newNavProp.Add(entity); } }); parentEntity.NavigationPropertyDataDic.TryUpdate(inf.Key.PropertyInfo.Name, newNavProp, navContainer); parentEntity.CallNavigationPropertyChangedByCache(parentEntity, inf.Key.PropertyInfo.Name); } // (en.NavigationPropertyDataDic[inf.Key.PropertyInfo.Name] as IList).Remove(itemToRemove); } else { //en[inf.Key.PropertyInfo.Name] = null; object tmp; parentEntity.NavigationPropertyDataDic.TryRemove(inf.Key.PropertyInfo.Name, out tmp); parentEntity.CallNavigationPropertyChangedByCache(parentEntity, inf.Key.PropertyInfo.Name); } } else { parentEntity.CallNavigationPropertyChangedByCache(parentEntity, inf.Key.PropertyInfo.Name); } })); } } } cacheInfo.MaxTimeStampUintForDeletedRecord = cacheInfo.MaxTimeStampUintForDeletedRecord2; cacheInfo.MaxTimeStampUintForDeletedRecord2 = maxTimeStampDeletedRecords; cacheInfo.MaxTimeStampForDeletedRecord = cacheInfo.MaxTimeStampForDeletedRecord2; cacheInfo.MaxTimeStampForDeletedRecord2 = maxDeletedRecordItem.TimeStamp; } } if (nlst.Count > 0) { entitiesForAddition = new List <ObjectBase>(); entitiesForUpdates = new List <ObjectBase>(); var newLst = nlst.Cast <ObjectBase>().ToList(); var oldLst = (oldData as IList); var oldEntityBaseLst = (oldData as IList).Cast <ObjectBase>().ToList(); var result = Activator.CreateInstance <T>() as IList; foreach (var item in oldEntityBaseLst) { result.Add(item); } foreach (var newItem in newLst) { var oldItem = oldEntityBaseLst.FirstOrDefault(item => item.Equals(newItem)); if (oldItem != null) { UpdateNavigationProperties(cacheInfo, newItem, oldItem); oldItem.UpdateAllProps(newItem); entitiesForUpdates.Add(oldItem); } else { entitiesForAddition.Add(newItem); result.Add(newItem); UpdateNavigationProperties(cacheInfo, newItem, null); // newItem.EnableFillNavigationProperyByCache = true; } } resultList = (T)result; } } if (entitiesForUpdates != null && entitiesForUpdates.Count > 0) { cacheInfo.CallOnUpdateEntities(entitiesForUpdates); } if (entitiesForAddition != null && entitiesForAddition.Count > 0) { cacheInfo.CallOnAddEntities(entitiesForAddition); } if (entitiesForDeletion != null && entitiesForDeletion.Count > 0) { cacheInfo.CallOnDeleteEntities(entitiesForDeletion); } if ((cacheInfo.EnableUseCacheServer && ConfigHelper.GetConfigValue <bool>("IsCacheServer")) || !cacheInfo.EnableUseCacheServer) { if (!string.IsNullOrEmpty(cacheInfo.NameOfNavigationPropsForFetchingOnlyChangedDataFromDB) || (cacheInfo.EnableSaveCacheOnHDD && cacheInfo.NotYetGetCacheData)) { QueryableCacheDataProvider <object> .CalcAllTimeStampAndSet(newData as IList, cacheInfo, isQueryableCache); } else { cacheInfo.MaxTimeStamp = cacheInfo.MaxTimeStampCopy; cacheInfo.MaxTimeStampUint = cacheInfo.MaxTimeStampUintCopy; } } if (nlst.Count > 0) { foreach (var en in nlst.Cast <ObjectBase>()) { (en as ObjectBase).EnableFillNavigationProperyByCache(); } } // System.Diagnostics.Debug.WriteLine("after merg:" + (oldData as IList).Count); return(resultList); }
private static void RefreshCache_Force <T>(ICacheDataProvider <T> cacheExecution, CacheInfo cacheInfo, T oldCacheValue, out T refreshCacheValue) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); var cacheKey = cacheExecution.GenerateCacheKey(); var cacheKeyFake = cacheKey + "_Fake"; try { refreshCacheValue = cacheExecution.GetFreshData(); List <ObjectBase> entitiesForDeletion = null; List <ObjectBase> entitiesForAddition = null; List <ObjectBase> entitiesForUpdates = null; lock (cacheInfo.InfoAndEntityListForFillingNavigationPropertyDic) { if (cacheInfo.EnableToFetchOnlyChangedDataFromDB) { refreshCacheValue = MergeFreshDataByOldCache <T>(oldCacheValue, refreshCacheValue, cacheInfo, true, out entitiesForDeletion, out entitiesForAddition, out entitiesForUpdates); } CacheService.SetCache <T>(cacheExecution.GenerateCacheKey(), refreshCacheValue, cacheInfo.AutoRefreshInterval * (double)100000); cacheInfo.NotYetGetCacheData = false; } if (entitiesForUpdates != null && entitiesForUpdates.Count > 0) { cacheInfo.CallAfterUpdateEntities(entitiesForUpdates); } if (entitiesForAddition != null && entitiesForAddition.Count > 0) { cacheInfo.CallAfterAddEntities(entitiesForAddition); } if (entitiesForDeletion != null && entitiesForDeletion.Count > 0) { cacheInfo.CallAfterDeleteEntities(entitiesForDeletion); } cacheInfo.FrequencyOfBuilding += 1; cacheInfo.LastBuildDateTime = DateTime.Now; stopwatch.Stop(); var time = new TimeSpan(stopwatch.ElapsedTicks); cacheInfo.BuildingTime += time; } catch (Exception ex) { cacheInfo.ErrorCount = cacheInfo.ErrorCount + 1; //System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace(ex, true); //System.Diagnostics.StackFrame[] frames = st.GetFrames(); //string x = ""; //// Iterate over the frames extracting the information you need //foreach (System.Diagnostics.StackFrame frame in frames) //{ // // x = ""+ frame.GetFileName()+""; // x += "filename:" + frame.GetFileName() + "--methodname:" + frame.GetMethod().Name + "--linenumber:" + frame.GetFileLineNumber() + "--columnnumber:" + frame.GetFileColumnNumber(); //} CacheService.RemoveCache(cacheKeyFake); //var eLog = _logService.GetEventLogObj(); //eLog.OccuredException = ex; //eLog.UserId = "dbContext Cache in Thread !"; //eLog.CustomMessage = x; //_logService.Handle(eLog); refreshCacheValue = default(T); throw _logService.Handle(ex, "dbContext Cache in Thread !"); } }
private static bool TryRefreshCache <T>(ICacheDataProvider <T> cacheExecution, CacheInfo cacheInfo, out T refreshCacheValue) { try { refreshCacheValue = RefreshCache <T>(cacheExecution, cacheInfo); return(true); } catch { refreshCacheValue = default(T); return(false); } }
private static void BuildCachesInAssembly(Type dBContext, Assembly repAssembly, bool isRepositoryAssembly) { IEnumerable <MethodInfo> types = null; try { types = repAssembly.GetTypes() .SelectMany(type => type.GetMethods(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)); } catch { //This exception is don't care. return; } foreach (var type in types) { var cacheInfoAtt = type.GetAttributeValue <CacheableAttribute, CacheableAttribute>(cAtt => cAtt); if (cacheInfoAtt != null) { //if (string.IsNullOrEmpty(cacheInfo.Key)) //{ // throw new ArgumentNullException("Cache Key can't be empty."); //} if ((type as MethodInfo).IsStatic) { if (!(type as MethodInfo).IsGenericMethod) { var methodInfo = type as MethodInfo; var parames = methodInfo.GetParameters(); Type funcBaseType = null; if (parames.Count() == 0) { funcBaseType = typeof(Func <>); } if (parames.Count() == 1) { funcBaseType = typeof(Func <,>); } if (parames.Count() == 2) { funcBaseType = typeof(Func <, ,>); } if (parames.Count() == 3) { funcBaseType = typeof(Func <, , ,>); } if (parames.Count() == 4) { funcBaseType = typeof(Func <, , , ,>); } if (parames.Count() == 5) { funcBaseType = typeof(Func <, , , , ,>); } List <Type> tArgs = methodInfo.GetParameters().Select(item => item.ParameterType).ToList(); tArgs.Add(methodInfo.ReturnType); var funcType = funcBaseType.MakeGenericType(tArgs.ToArray()); var funcInstanc = methodInfo.CreateDelegate(funcType); var key = funcInstanc.Method.GetHashCode().ToString(); CacheInfo currentCacheInfo = null; if (!CacheInfoDic.TryGetValue(key, out currentCacheInfo)) { // throw new ArgumentException("Duplicate cache key can't be used , please use an unique key for cache."); currentCacheInfo = CreateCacheInfo(cacheInfoAtt, methodInfo, funcInstanc, key); } try { if (typeof(IQueryable).IsAssignableFrom(methodInfo.ReturnType) && parames.Length > 0 && typeof(IQueryable).IsAssignableFrom(parames[0].ParameterType)) { if (!isRepositoryAssembly) { throw new NotSupportedException("Queryable Cache just can use in Repository Layer."); } var repository = (IRepositoryCache)Activator.CreateInstance(methodInfo.DeclaringType, Activator.CreateInstance(dBContext)); currentCacheInfo.Repository = repository; if (parames.Length == 1) { var cacheDataProviderType = typeof(QueryableCacheDataProvider <>); Type[] typeArgs = methodInfo.ReturnType.GenericTypeArguments; var cacheDataProviderGenericType = cacheDataProviderType.MakeGenericType(typeArgs); var returnCacheType = typeof(List <>).MakeGenericType(methodInfo.ReturnType.GenericTypeArguments[0]); CacheWCFTypeHelper.typeList.Add(cacheDataProviderGenericType); CacheWCFTypeHelper.typeList.Add(methodInfo.ReturnType.GenericTypeArguments[0]); CacheWCFTypeHelper.typeList.Add(returnCacheType); // if (currentCacheInfo.EnableUseCacheServer) // CacheWCFTypeHelper.typeList.Add(methodInfo.ReturnType); object queryableCacheExecution = Activator.CreateInstance(cacheDataProviderGenericType, new object[] { currentCacheInfo }); if (currentCacheInfo.FrequencyOfBuilding == 0) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); if (!cacheInfoAtt.DisableCache) { (typeof(CacheBase)).GetMethod("RefreshCache").MakeGenericMethod(returnCacheType).Invoke(null, new object[] { queryableCacheExecution, currentCacheInfo }); } stopwatch.Stop(); currentCacheInfo.FrequencyOfBuilding += 1; currentCacheInfo.BuildingTime += new TimeSpan(stopwatch.ElapsedTicks); } if (currentCacheInfo.CacheRefreshingKind == CacheRefreshingKind.Slide) { PeriodicTaskFactory p = new PeriodicTaskFactory((pt) => { if (currentCacheInfo.CountOfWaitingThreads < 3) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); ((IQueryableCacheDataProvider)queryableCacheExecution).DbContext = AppBase.DependencyInjectionFactory.CreateContextInstance(); (typeof(CacheBase)).GetMethod("RefreshCache").MakeGenericMethod(returnCacheType).Invoke(null, new object[] { queryableCacheExecution, currentCacheInfo }); stopwatch.Stop(); currentCacheInfo.FrequencyOfBuilding += 1; currentCacheInfo.BuildingTime += new TimeSpan(stopwatch.ElapsedTicks); } }, new TimeSpan(0, 0, currentCacheInfo.AutoRefreshInterval), new TimeSpan(0, 0, currentCacheInfo.AutoRefreshInterval)); p.Start(); } else { if (currentCacheInfo.CacheRefreshingKind == CacheRefreshingKind.SqlDependency) { if (currentCacheInfo.EnableSaveCacheOnHDD && currentCacheInfo.EnableToFetchOnlyChangedDataFromDB) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); if (!cacheInfoAtt.DisableCache) { ((IQueryableCacheDataProvider)queryableCacheExecution).DbContext = AppBase.DependencyInjectionFactory.CreateContextInstance(); (typeof(CacheBase)).GetMethod("RefreshCache").MakeGenericMethod(returnCacheType).Invoke(null, new object[] { queryableCacheExecution, currentCacheInfo }); } stopwatch.Stop(); currentCacheInfo.FrequencyOfBuilding += 1; currentCacheInfo.BuildingTime += new TimeSpan(stopwatch.ElapsedTicks); } var typeOfSqlNotifier = typeof(IImmediateSqlNotificationRegister <>) .MakeGenericType(currentCacheInfo.Repository.GetDomainModelType()); IImmediateSqlNotificationRegisterBase immediateSqlNotificationRegister = (IImmediateSqlNotificationRegisterBase) AppBase.DependencyInjectionManager.Resolve(typeOfSqlNotifier, new ParameterOverride("context", ((IQueryableCacheDataProvider)queryableCacheExecution).DbContext), new ParameterOverride("query", ((IQueryableCacheDataProvider)queryableCacheExecution).GetQuery())); using (var trace = new Trace.TraceDto()) { trace.TraceKey = "CacheSqlDependency"; trace.Data["CacheName"] = currentCacheInfo.Name; trace.Data["DateTime"] = DateTime.Now.ToString(); trace.Message = $"CacheSql Dependency {currentCacheInfo.Name} before configouration on startup at {DateTime.Now.ToString()} ..."; trace.Data["State"] = "config"; Core.Cmn.AppBase.TraceWriter.SubmitData(trace); } immediateSqlNotificationRegister.OnChanged += (object sender, SqlNotificationEventArgs e) => { if (currentCacheInfo.CountOfWaitingThreads < 3) { using (var trace = new Trace.TraceDto()) { trace.TraceKey = "CacheSqlDependency"; trace.Data["CacheName"] = currentCacheInfo.Name; trace.Data["DateTime"] = DateTime.Now.ToString(); trace.Message = $"CacheSql Dependency {currentCacheInfo.Name} before changing at {DateTime.Now.ToString()} ..."; trace.Data["State"] = "changing"; Core.Cmn.AppBase.TraceWriter.SubmitData(trace); } Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); ((IQueryableCacheDataProvider)queryableCacheExecution).DbContext = AppBase.DependencyInjectionFactory.CreateContextInstance(); immediateSqlNotificationRegister.Init(((IQueryableCacheDataProvider)queryableCacheExecution).DbContext, ((IQueryableCacheDataProvider)queryableCacheExecution).GetQuery(), currentCacheInfo); ExcecuteQueryForRefreshingSqlDependencyCache(currentCacheInfo, returnCacheType, queryableCacheExecution, 500); stopwatch.Stop(); currentCacheInfo.FrequencyOfBuilding += 1; currentCacheInfo.BuildingTime += new TimeSpan(stopwatch.ElapsedTicks); using (var trace = new Trace.TraceDto()) { trace.TraceKey = "CacheSqlDependency"; trace.Data["CacheName"] = currentCacheInfo.Name; trace.Data["DateTime"] = DateTime.Now.ToString(); trace.Message = $"CacheSql Dependency {currentCacheInfo.Name} was changed at {DateTime.Now.ToString()} ..."; trace.Data["State"] = "changing"; Core.Cmn.AppBase.TraceWriter.SubmitData(trace); } } }; using (var trace = new Trace.TraceDto()) { trace.TraceKey = "CacheSqlDependency"; trace.Data["CacheName"] = currentCacheInfo.Name; trace.Data["DateTime"] = DateTime.Now.ToString(); trace.Message = $"CacheSql Dependency {currentCacheInfo.Name} was configured on startup at {DateTime.Now.ToString()} ..."; trace.Data["State"] = "config"; Core.Cmn.AppBase.TraceWriter.SubmitData(trace); } } } } if (currentCacheInfo.EnableToFetchOnlyChangedDataFromDB && !currentCacheInfo.DisableToSyncDeletedRecord_JustIfEnableToFetchOnlyChangedDataFromDB) { CacheManagementRepository.CreateSqlTriggerForDetectingDeletedRecords(string.Format("{0}.{1}", repository.Schema, repository.TableName), repository.KeyName); } } else { if (isRepositoryAssembly) { throw new NotSupportedException("Functional Cache just can use in Service Layer."); } var Service = (IServiceCache)Activator.CreateInstance(methodInfo.DeclaringType, Activator.CreateInstance(dBContext)); Core.Cmn.AppBase.TraceWriter.SubmitData(new Trace.TraceDto { Message = $"{currentCacheInfo.Name} BuildCachesInAssembly start..." }); currentCacheInfo.Service = Service; Type cacheDataProviderType = null; if (parames.Length == 0) { cacheDataProviderType = typeof(FunctionalCacheDataProvider <>); var cacheDataProviderGenericType = AddAndGetCacheDataProviderTypeForSerialization(methodInfo, cacheDataProviderType); object functionalCacheExecution = Activator.CreateInstance(cacheDataProviderGenericType, new object[] { currentCacheInfo }); if (currentCacheInfo.FrequencyOfBuilding == 0) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); if (!cacheInfoAtt.DisableCache) { (typeof(CacheBase)).GetMethod("RefreshCache").MakeGenericMethod(methodInfo.ReturnType).Invoke(null, new object[] { functionalCacheExecution, currentCacheInfo }); } stopwatch.Stop(); currentCacheInfo.FrequencyOfBuilding += 1; currentCacheInfo.BuildingTime += new TimeSpan(stopwatch.ElapsedTicks); } if (currentCacheInfo.CacheRefreshingKind == CacheRefreshingKind.Slide) { PeriodicTaskFactory p = new PeriodicTaskFactory((pt) => { if (currentCacheInfo.CountOfWaitingThreads < 3) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); (typeof(CacheBase)).GetMethod("RefreshCache").MakeGenericMethod(methodInfo.ReturnType).Invoke(null, new object[] { functionalCacheExecution, currentCacheInfo }); stopwatch.Stop(); currentCacheInfo.FrequencyOfBuilding += 1; currentCacheInfo.BuildingTime += new TimeSpan(stopwatch.ElapsedTicks); } }, new TimeSpan(0, 0, currentCacheInfo.AutoRefreshInterval), new TimeSpan(0, 0, currentCacheInfo.AutoRefreshInterval)); p.Start(); } } else { if (parames.Length == 1) { cacheDataProviderType = typeof(FunctionalCacheDataProvider <,>); } if (parames.Length == 2) { cacheDataProviderType = typeof(FunctionalCacheDataProvider <, ,>); } if (parames.Length == 3) { cacheDataProviderType = typeof(FunctionalCacheDataProvider <, , ,>); } if (parames.Length == 4) { cacheDataProviderType = typeof(FunctionalCacheDataProvider <, , , ,>); } if (parames.Length == 5) { cacheDataProviderType = typeof(FunctionalCacheDataProvider <, , , , ,>); } AddAndGetCacheDataProviderTypeForSerialization(methodInfo, cacheDataProviderType); } Core.Cmn.AppBase.TraceWriter.SubmitData(new Trace.TraceDto { Message = $"{currentCacheInfo.Name} BuildCachesInAssembly done." }); } } catch (Exception exception) { Core.Cmn.AppBase.LogService.Handle(exception, $"{exception.Message}. Cache name: {currentCacheInfo?.Name}"); throw; } currentCacheInfo.LastBuildDateTime = DateTime.Now; } else { if (cacheInfoAtt.EnableAutomaticallyAndPeriodicallyRefreshCache) { throw new NotSupportedException($"a generic method can't call automatically for cache.If you want to use generic method set '{nameof(cacheInfoAtt.CacheRefreshingKind)}' = {nameof(CacheRefreshingKind.Slide)} in CacheableAttribute"); } } } else { throw new NotSupportedException("Cacheable Attribute can't use on Non static methods, because we can't work on nostatic method for caching."); } } } }