Как продолжение этого топика про кэш хочу предложить вам свое, частично стыренное решение для кеширования не очень больших таблиц. Для этого просто создадим новый extension метод:
Пользоваться этим проще простого:
1) добавляем в Global.asax
2) используем в приложении:
PS для работы данного метода у вас должен быть включен SQL server broker
PPS транзакции использовать необязательно, это куски кода с текущего проекта:)
Copy Source | Copy HTML
- public static class CachingHelper
- {
- /// <summary>
- /// строка соединения с базой
- /// </summary>
- private static string conString = System.Configuration.ConfigurationManager.ConnectionStrings["pltfrmDBConnectionString"].ConnectionString;
-
- /// <summary>
- /// Cache instance object
- /// </summary>
- private static volatile Cache cache = HttpContext.Current.Cache;
-
- /// <summary>
- /// Object for proper locking of cache additions/removals
- /// </summary>
- private static object syncRoot = new object();
-
- /// <summary>
- /// Кэширует и получает объекты из кэша
- /// </summary>
- /// <param name="query">Таблица для кэширования</param>
- /// <typeparam name="T">Тип объектов в Таблице</typeparam>
- /// <returns>Массив объектов типа T</returns>
- public static T[] LinqCache<T>(this Table<T> query) where T : class
- {
- var tableName = query.Context.Mapping.GetTable(typeof(T)).TableName;
- var result = cache[tableName] as T[];
- if (result != null)
- {
- return result;
- }
-
- var trop = new TransactionOptions
- {
- IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted
- };
- var req = TransactionScopeOption.Required;
-
- if (Transaction.Current == null || Transaction.Current.TransactionInformation.Status == TransactionStatus.Aborted)
- {
- req = TransactionScopeOption.RequiresNew;
- }
-
- using (var ts = new TransactionScope(req, trop))
- {
- using (var cn = new SqlConnection(conString))
- {
- try
- {
- cn.Open();
- var cmdText = query.Context.GetCommand(query).CommandText;
- var cmd = new SqlCommand(cmdText, cn)
- {
- NotificationAutoEnlist = true,
- Notification = null,
- CommandType = CommandType.Text
- };
-
- foreach (DbParameter dbp in query.Context.GetCommand(query).Parameters)
- {
- cmd.Parameters.Add(new SqlParameter(dbp.ParameterName, dbp.Value));
- }
-
- var dependency = new SqlCacheDependency(cmd);
-
- cmd.ExecuteNonQuery();
-
- result = query.ToArray();
-
- cache.Insert(tableName, result, dependency);
- }
- catch (SqlException e)
- {
- if (e.Number == 4060)
- {
- throw new AuthenticationException("Авторизация не пройдена");
- }
-
- throw;
- }
- }
-
- ts.Complete();
- }
-
- return result;
- }
- }
Пользоваться этим проще простого:
1) добавляем в Global.asax
Copy Source | Copy HTML
- /// <summary>
- /// Событие старта приложения
- /// </summary>
- /// <param name="sender">
- /// Вызывающий объект
- /// </param>
- /// <param name="e">
- /// Аргументы события
- /// </param>
- protected void Application_Start(object sender, EventArgs e)
- {
- SqlDependency.Start(ConfigurationManager.ConnectionStrings["pltfrmDBConnectionString"].ConnectionString);
- }
-
- /// <summary>
- /// Событие завершения приложения
- /// </summary>
- /// <param name="sender">
- /// Вызывающий объект
- /// </param>
- /// <param name="e">
- /// Аргументы события
- /// </param>
- protected void Application_End(object sender, EventArgs e)
- {
- SqlDependency.Stop(ConfigurationManager.ConnectionStrings["pltfrmDBConnectionString"].ConnectionString);
- }
2) используем в приложении:
Copy Source | Copy HTML
- var db = new SomeContext();
- var cached = db.SomeTable.LinqCache().Where(a => a.b == "qwe");
PS для работы данного метода у вас должен быть включен SQL server broker
PPS транзакции использовать необязательно, это куски кода с текущего проекта:)