データベースから頻繁にロードされるデータを Web アプリケーションのサーバーの MemoryCache に保存したいと考えています。クラスがキャッシュにアクセスしてオブジェクトを取得するたびに、オブジェクトからの参照で ObjectDisposedException 例外が発生します。したがって、データベースの外部のどこかにすべての参照を含むオブジェクトを格納できるかどうかを知る必要があります。
例: これが私の ModelCache の主なメソッドです。他のメソッドは Singelton で、GlobalCachingProvider は通常どおり実装されます。
public virtual bool GetAnimalLineFromCache(int id, int userId, out AnimalLine animalLine, out Dictionary<PermissionEnum, bool> permissions)
{
try
{
Tuple<AnimalLine, Dictionary<IAzaraUser, Dictionary<PermissionEnum, bool>>> dic;
if (GlobalCachingProvider.Instance.CheckIfSpecificCacheExists("AnimalLine_" + id))
{
dic = GlobalCachingProvider.Instance.GetItem("AnimalLine_" + id) as Tuple<AnimalLine, Dictionary<IAzaraUser, Dictionary<PermissionEnum, bool>>>;
animalLine = dic.Item1 as AnimalLine;
if (dic.Item2.Any(c => c.Key.Id == userId))
{
permissions = dic.Item2.SingleOrDefault(x => x.Key.Id == userId).Value;
return true;
}
else
{
permissions = null;
return false;
}
}
else
{
animalLine = null;
permissions = null;
return false;
}
}
catch (Exception exc)
{
using (var dataContext = new AzaraDataContext())
{
var errorManagement = new ErrorLogManagement(dataContext);
errorManagement.InsertErrorLog(exc.Message, exc.StackTrace, "ModelCacheManagement", "GetAnimalLineFromCache");
}
animalLine = null;
permissions = null;
return false;
}
}
public virtual void StoreAnimalLineInCache(AnimalLine animalLine, IAzaraUser user, bool read, bool edit, bool delete)
{
try
{
if (user == null) user = new AzaraUser() { Id = 0 };
Tuple<AnimalLine, Dictionary<IAzaraUser, Dictionary<PermissionEnum, bool>>> dic;
if (GlobalCachingProvider.Instance.CheckIfSpecificCacheExists("AnimalLine_" + animalLine.Id))
{
dic = GlobalCachingProvider.Instance.GetItem("AnimalLine_" + animalLine.Id) as Tuple<AnimalLine, Dictionary<IAzaraUser, Dictionary<PermissionEnum, bool>>>;
var Permissions = new Dictionary<PermissionEnum, bool>();
Permissions.Add(PermissionEnum.Read, read);
Permissions.Add(PermissionEnum.Edit, edit);
Permissions.Add(PermissionEnum.Delete, delete);
dic.Item2.Add(user, Permissions);
GlobalCachingProvider.Instance.ReplaceItem("AnimalLine_" + animalLine.Id, dic);
}
else
{
var Permissions = new Dictionary<PermissionEnum, bool>();
Permissions.Add(PermissionEnum.Read, read);
Permissions.Add(PermissionEnum.Edit, edit);
Permissions.Add(PermissionEnum.Delete, delete);
var dic2 = new Dictionary<IAzaraUser, Dictionary<PermissionEnum, bool>>();
dic2.Add(user, Permissions);
dic = Tuple.Create<AnimalLine, Dictionary<IAzaraUser, Dictionary<PermissionEnum, bool>>>(animalLine, dic2);
GlobalCachingProvider.Instance.AddItem("AnimalLine_" + animalLine.Id, dic);
}
}
catch (Exception exc)
{
using (var dataContext = new AzaraDataContext())
{
var errorManagement = new ErrorLogManagement(dataContext);
errorManagement.InsertErrorLog(exc.Message, exc.StackTrace, "ModelCacheManagement", "StoreAnimalLineInCache");
}
}
}
次に、コントローラーまたは独自の DataContext インスタンスを持つ他のクラスからこれらのメソッドにアクセスするメソッドの 1 つを次に示します。
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (httpContext == null) throw new ArgumentNullException("httpContext");
int Id = 0;
int userId = UserCacheManagement.Instance.GetUserFromCache(AzaraSession.Current.SessionID).GetUserId();
AnimalLine animalLine = null;
Id = int.Parse((httpContext.Request.RequestContext.RouteData.Values["animalLineId"] as string) ?? (httpContext.Request["animalLineId"] as string)); break;
Dictionary<PermissionEnum, bool> permissions = null;
ModelCacheManagement.Instance.GetAnimalLineFromCache(Id, userId, out animalLine, out permissions);
if (permissions != null) return permissions[permissionType];
using (var dataContext = new AzaraDataContext())
{
try
{
PermissionControle permissionControle = new PermissionControle(dataContext);
IEntityManagement<AzaraUser> azaraUserManagement = new AzaraUserManagement(dataContext);
var user = userId != 0 ? azaraUserManagement.GetSingle(userId) : null;
var userVisibility = permissionControle.GetVisibility(String.IsNullOrEmpty(user.UserName) ? "" : user.UserName);
var lineManagement = new LineManagement(dataContext);
animalLine = lineManagement.GetSingle(Id) as AnimalLine;
ISecurableEntity iSecEnt = animalLine as ISecurableEntity;
var read = iSecEnt != null ? permissionControle.CanUserRead(user, iSecEnt) : false;
var edit = iSecEnt != null ? permissionControle.CanUserEdit(user, iSecEnt) : false;
var delete = iSecEnt != null ? permissionControle.CanUserDelete(user, iSecEnt) : false;
ModelCacheManagement.Instance.StoreAnimalLineInCache(animalLine, user, read, edit, delete);
switch (permissionType)
{
case PermissionEnum.Read: return read;
case PermissionEnum.Edit: return edit;
case PermissionEnum.Delete: return delete;
}
return false;
}
catch (Exception exc)
{
var errorManagement = new ErrorLogManagement(dataContext);
errorManagement.InsertErrorLog(exc.Message, exc.StackTrace, "PermissionAuthorizationAttribute", "AuthorizeCore");
return false;
}
}
}