试图从多个缓存条目中引用 CacheDependency 对象
An attempt was made to reference a CacheDependency object from more than one Cache entry
代码一:
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
AggregateCacheDependency XmlFileCacheDependencyForBirds
=
new
AggregateCacheDependency();
XmlFileCacheDependencyForBirds.Add(
new CacheDependency(HttpContext.Current.Server.MapPath( " App_Data/Product.xml " )),
new CacheDependency(HttpContext.Current.Server.MapPath( " App_Data/Category.xml " )));
HttpRuntime.Cache.Add( " cacheKey1 " , " cacheData1 " , XmlFileCacheDependencyForBirds,
DateTime.MaxValue, new TimeSpan( 1 , 1 , 1 ), CacheItemPriority.High, null );
HttpRuntime.Cache.Add( " cacheKey2 " , " cacheData2 " , XmlFileCacheDependencyForBirds,
DateTime.MaxValue, new TimeSpan( 1 , 1 , 1 ), CacheItemPriority.High, null );
XmlFileCacheDependencyForBirds.Add(
new CacheDependency(HttpContext.Current.Server.MapPath( " App_Data/Product.xml " )),
new CacheDependency(HttpContext.Current.Server.MapPath( " App_Data/Category.xml " )));
HttpRuntime.Cache.Add( " cacheKey1 " , " cacheData1 " , XmlFileCacheDependencyForBirds,
DateTime.MaxValue, new TimeSpan( 1 , 1 , 1 ), CacheItemPriority.High, null );
HttpRuntime.Cache.Add( " cacheKey2 " , " cacheData2 " , XmlFileCacheDependencyForBirds,
DateTime.MaxValue, new TimeSpan( 1 , 1 , 1 ), CacheItemPriority.High, null );
代码二:
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
using
System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Caching;
using System.Xml;
/// <summary>
/// Summary description for CacheManager
/// </summary>
public class TestCacheManager
{
private static bool _productsRemovedFromCache = false ;
// 记录访问从xml读取数据的相关信息
private static Dictionary < string , string > _logs = new Dictionary < string , string > ();
public static Dictionary < string , string > Logs
{
get { return _logs; }
}
private static string productxmlPath;
private static string categoryxmlPath;
private static AggregateCacheDependency XmlFileCacheDependencyForBirds = new AggregateCacheDependency();
private static AggregateCacheDependency XmlFileCacheDependencyForBugs = new AggregateCacheDependency();
static TestCacheManager()
{
productxmlPath = HttpContext.Current.Server.MapPath( " App_Data/Product.xml " );
categoryxmlPath = HttpContext.Current.Server.MapPath( " App_Data/Category.xml " );
XmlFileCacheDependencyForBirds.Add(
new CacheDependency(HttpContext.Current.Server.MapPath( " App_Data/Product.xml " )),
new CacheDependency(HttpContext.Current.Server.MapPath( " App_Data/Category.xml " )));
XmlFileCacheDependencyForBugs.Add(
new CacheDependency(HttpContext.Current.Server.MapPath( " App_Data/Product.xml " )),
new CacheDependency(HttpContext.Current.Server.MapPath( " App_Data/Category.xml " )));
}
private static AggregateCacheDependency GetAggregateCacheDependency( string categoryKey)
{
switch (categoryKey)
{
case " BIRDS " :
return XmlFileCacheDependencyForBirds;
case " BUGS " :
return XmlFileCacheDependencyForBugs;
default :
return null ;
}
}
// 从缓存中获取项
public static List < Product > GetProductsByCategory( string categoryKey)
{
// 不应在 ASP.NET 页中实现回调处理程序,因为在从缓存中删除项之前该页可能已被释放,因此用于处理回调的方法将不可用,应该在非ASP.NET的程序集中实现回调处理程序。为了确保从缓存中删除项时处理回调的方法仍然存在,请使用该方法的静态类。但是,静态类的缺点是需要保证所有静态方法都是线程安全的,所以使用lock关键字。
lock ( typeof (CacheManager))
{
if (HttpContext.Current.Cache[categoryKey] != null )
{ // 存在缓存项,返回缓存值
return (List < Product > )HttpRuntime.Cache[categoryKey];
}
else
{ // 缓存项不存在,则创建缓存项
CacheProducts(categoryKey);
return (List < Product > )HttpRuntime.Cache[categoryKey];
}
}
}
// 将项以 的名称添加到缓存中,并将该项设置为在添加到缓存中后一分钟过期。 // 并且该方法注册 ReportRemoveCallback 方法,以便在从缓存中删除项时进行调用。
public static void CacheProducts( string categoryKey)
{
lock ( typeof (CacheManager))
{
// To avoid error that An attempt was made to reference a CacheDependency object from more than one Cache entry.
// AggregateCacheDependency acd = new AggregateCacheDependency();
// acd.Add(
// new CacheDependency(productxmlPath),
// new CacheDependency(categoryxmlPath));
HttpRuntime.Cache.Add(
categoryKey,
CreateProducts(categoryKey),
// acd,
// An attempt was made to reference a CacheDependency object from more than one Cache entry.
GetAggregateCacheDependency(categoryKey),
DateTime.MaxValue,
new TimeSpan( 1 , 1 , 1 ),
System.Web.Caching.CacheItemPriority.Default,
// 使用委托,在缓存删除时调用特定函数来响应。
ProductsRemovedCallback);
}
}
// 创建报告,该报告时缓存项的值
private static List < Product > CreateProducts( string categoryKey)
{
List < Product > lstProduct = new List < Product > ();
XmlDocument doc = new XmlDocument();
// HttpContext.Current.Server.MapPath("App_Data/Product.xml") Cache 失效后触发此函数时,HttpContext.Current 可能为Null
doc.Load(productxmlPath);
XmlNodeList productNodeList = doc.SelectNodes( string .Format( " Products/Product[@CategoryId='{0}'] " , categoryKey));
foreach (XmlNode productNode in productNodeList)
{
Product pro = new Product(productNode.Attributes[ " ProductId " ].Value.ToString()
, productNode.Attributes[ " Name " ].Value.ToString()
, productNode.Attributes[ " Descn " ].Value.ToString()
, productNode.Attributes[ " Image " ].Value.ToString()
, productNode.Attributes[ " CategoryId " ].Value.ToString());
lstProduct.Add(pro);
}
_logs.Remove(categoryKey);
_logs.Add(categoryKey, string .Format( " {1} (Access xml file to get product {0}'s data) " , categoryKey, DateTime.Now.ToString()));
return lstProduct;
}
/// <summary>
/// 当从缓存中删除项时调用该方法
/// </summary>
/// <param name="key"> CacheKey </param>
/// <param name="value"> Cache Data </param>
/// <param name="removedReason"> Removed/Expired/Underused/DependencyChanged </param>
public static void ProductsRemovedCallback(String key, object value,
CacheItemRemovedReason removedReason)
{
_productsRemovedFromCache = true ;
CacheProducts(key);
}
}
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Caching;
using System.Xml;
/// <summary>
/// Summary description for CacheManager
/// </summary>
public class TestCacheManager
{
private static bool _productsRemovedFromCache = false ;
// 记录访问从xml读取数据的相关信息
private static Dictionary < string , string > _logs = new Dictionary < string , string > ();
public static Dictionary < string , string > Logs
{
get { return _logs; }
}
private static string productxmlPath;
private static string categoryxmlPath;
private static AggregateCacheDependency XmlFileCacheDependencyForBirds = new AggregateCacheDependency();
private static AggregateCacheDependency XmlFileCacheDependencyForBugs = new AggregateCacheDependency();
static TestCacheManager()
{
productxmlPath = HttpContext.Current.Server.MapPath( " App_Data/Product.xml " );
categoryxmlPath = HttpContext.Current.Server.MapPath( " App_Data/Category.xml " );
XmlFileCacheDependencyForBirds.Add(
new CacheDependency(HttpContext.Current.Server.MapPath( " App_Data/Product.xml " )),
new CacheDependency(HttpContext.Current.Server.MapPath( " App_Data/Category.xml " )));
XmlFileCacheDependencyForBugs.Add(
new CacheDependency(HttpContext.Current.Server.MapPath( " App_Data/Product.xml " )),
new CacheDependency(HttpContext.Current.Server.MapPath( " App_Data/Category.xml " )));
}
private static AggregateCacheDependency GetAggregateCacheDependency( string categoryKey)
{
switch (categoryKey)
{
case " BIRDS " :
return XmlFileCacheDependencyForBirds;
case " BUGS " :
return XmlFileCacheDependencyForBugs;
default :
return null ;
}
}
// 从缓存中获取项
public static List < Product > GetProductsByCategory( string categoryKey)
{
// 不应在 ASP.NET 页中实现回调处理程序,因为在从缓存中删除项之前该页可能已被释放,因此用于处理回调的方法将不可用,应该在非ASP.NET的程序集中实现回调处理程序。为了确保从缓存中删除项时处理回调的方法仍然存在,请使用该方法的静态类。但是,静态类的缺点是需要保证所有静态方法都是线程安全的,所以使用lock关键字。
lock ( typeof (CacheManager))
{
if (HttpContext.Current.Cache[categoryKey] != null )
{ // 存在缓存项,返回缓存值
return (List < Product > )HttpRuntime.Cache[categoryKey];
}
else
{ // 缓存项不存在,则创建缓存项
CacheProducts(categoryKey);
return (List < Product > )HttpRuntime.Cache[categoryKey];
}
}
}
// 将项以 的名称添加到缓存中,并将该项设置为在添加到缓存中后一分钟过期。 // 并且该方法注册 ReportRemoveCallback 方法,以便在从缓存中删除项时进行调用。
public static void CacheProducts( string categoryKey)
{
lock ( typeof (CacheManager))
{
// To avoid error that An attempt was made to reference a CacheDependency object from more than one Cache entry.
// AggregateCacheDependency acd = new AggregateCacheDependency();
// acd.Add(
// new CacheDependency(productxmlPath),
// new CacheDependency(categoryxmlPath));
HttpRuntime.Cache.Add(
categoryKey,
CreateProducts(categoryKey),
// acd,
// An attempt was made to reference a CacheDependency object from more than one Cache entry.
GetAggregateCacheDependency(categoryKey),
DateTime.MaxValue,
new TimeSpan( 1 , 1 , 1 ),
System.Web.Caching.CacheItemPriority.Default,
// 使用委托,在缓存删除时调用特定函数来响应。
ProductsRemovedCallback);
}
}
// 创建报告,该报告时缓存项的值
private static List < Product > CreateProducts( string categoryKey)
{
List < Product > lstProduct = new List < Product > ();
XmlDocument doc = new XmlDocument();
// HttpContext.Current.Server.MapPath("App_Data/Product.xml") Cache 失效后触发此函数时,HttpContext.Current 可能为Null
doc.Load(productxmlPath);
XmlNodeList productNodeList = doc.SelectNodes( string .Format( " Products/Product[@CategoryId='{0}'] " , categoryKey));
foreach (XmlNode productNode in productNodeList)
{
Product pro = new Product(productNode.Attributes[ " ProductId " ].Value.ToString()
, productNode.Attributes[ " Name " ].Value.ToString()
, productNode.Attributes[ " Descn " ].Value.ToString()
, productNode.Attributes[ " Image " ].Value.ToString()
, productNode.Attributes[ " CategoryId " ].Value.ToString());
lstProduct.Add(pro);
}
_logs.Remove(categoryKey);
_logs.Add(categoryKey, string .Format( " {1} (Access xml file to get product {0}'s data) " , categoryKey, DateTime.Now.ToString()));
return lstProduct;
}
/// <summary>
/// 当从缓存中删除项时调用该方法
/// </summary>
/// <param name="key"> CacheKey </param>
/// <param name="value"> Cache Data </param>
/// <param name="removedReason"> Removed/Expired/Underused/DependencyChanged </param>
public static void ProductsRemovedCallback(String key, object value,
CacheItemRemovedReason removedReason)
{
_productsRemovedFromCache = true ;
CacheProducts(key);
}
}
代码一 vs. 代码二 运行是都将抛出 "An attempt was made to reference a CacheDependency object from more than one Cache entry" 的异常。
原因:每个CacheDependency 只与一个缓存项关联,要跟多个缓存项关联,只需要用相关参数新建CacheDependency对象即可。
解决方法: 只要确保每个CacheDependency 只与一个缓存项关联即可。 建议构建CacheDependency 、 Cache关联CacheDependency能够在同一单元里完成。类似如下:
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
//
Create a AggregateCacheDependency object from the factory
AggregateCacheDependency cd = DependencyFacade.GetItemDependency();
// Store the output in the data cache, and Add the necessary AggregateCacheDependency object
HttpRuntime.Cache.Add(key, data, cd, DateTime.Now.AddHours(itemTimeout), Cache.NoSlidingExpiration, CacheItemPriority.High, null );
---------------------------------------------------------------------------
AggregateCacheDependency acd = new AggregateCacheDependency();
acd.Add(
new CacheDependency(productxmlPath),
new CacheDependency(categoryxmlPath));
HttpRuntime.Cache.Add(
categoryKey,
CreateProducts(categoryKey),
acd,
// An attempt was made to reference a CacheDependency object from more than one Cache entry.
// GetAggregateCacheDependency(categoryKey),
DateTime.MaxValue,
new TimeSpan( 1 , 1 , 1 ),
System.Web.Caching.CacheItemPriority.Default,
// 使用委托,在缓存删除时调用特定函数来响应。
ProductsRemovedCallback);
AggregateCacheDependency cd = DependencyFacade.GetItemDependency();
// Store the output in the data cache, and Add the necessary AggregateCacheDependency object
HttpRuntime.Cache.Add(key, data, cd, DateTime.Now.AddHours(itemTimeout), Cache.NoSlidingExpiration, CacheItemPriority.High, null );
---------------------------------------------------------------------------
AggregateCacheDependency acd = new AggregateCacheDependency();
acd.Add(
new CacheDependency(productxmlPath),
new CacheDependency(categoryxmlPath));
HttpRuntime.Cache.Add(
categoryKey,
CreateProducts(categoryKey),
acd,
// An attempt was made to reference a CacheDependency object from more than one Cache entry.
// GetAggregateCacheDependency(categoryKey),
DateTime.MaxValue,
new TimeSpan( 1 , 1 , 1 ),
System.Web.Caching.CacheItemPriority.Default,
// 使用委托,在缓存删除时调用特定函数来响应。
ProductsRemovedCallback);