我问的原因是因为HttpContext.Current.Items
集合似乎是放置IDisposable
对象(例如DataContext
)的好地方,以便存储库可以透明地访问它而不需要将与特定ORM技术相关的任何依赖项注入到存储库中。这也将允许存储库决定是否参与UnitOfWork
或承担实际持续任何更改的额外责任。
例如:
页面:
protected void Page_Load(...)
{
Items[KeyValueFromConfigurationFile] = new DataContext();
var repo = new Repository();
var rootEntity = repo.GetById(1);
}
存储库:
public virtual TEntity GetById(int id)
{
var ctx = HttpContext.Current.Items[KeyValueFromConfigurationFile] as DataContext;
return ctx.TEntities.SingleOrDefault(p => p.Id == id);
}
当然,如果DataContext
集合中没有HttpContext.Current.Items
,我会检查空值并执行获取HttpContext.Current
所需的步骤。
所以,回到我给出上述代码的原始问题:即使抛出异常,{{1}}是否会与其Items集合中包含的任何对象一起处理? < / p>
答案 0 :(得分:13)
HttpContext.Current.Items中的对象不会自动处理。您需要自己处理。您可以在global.asax Application_EndRequest中执行此操作:
foreach (var item in HttpContext.Current.Items.Values)
{
var disposableItem = item as IDisposable;
if (disposableItem != null)
{
disposableItem.Dispose();
}
}
答案 1 :(得分:2)
我认为最后一篇提供解决方案的帖子没有问题,因为底层集合没有被修改,这在枚举时无法完成,但我最近遇到了这段代码的零星错误。我们看到错误'收集被修改;当OnEndRequest触发并执行下面的for循环时,枚举操作可能无法执行:
foreach (var item in HttpContext.Current.Items.Values)
{
var disposableItem = item as IDisposable;
if (disposableItem != null)
{
disposableItem.Dispose();
}
}
显然,在使用foreach循环迭代集合时处理当前的HttpContext项也会造成问题。有几种方法,但我选择这样做:
int size = HttpContext.Current.Items.Count;
if (size > 0)
{
var keys = new object[size];
HttpContext.Current.Items.Keys.CopyTo(keys, 0);
for (int i = 0; i < size; i++)
{
var obj = HttpContext.Current.Items[keys[i]] as IDisposable;
if (obj != null)
obj.Dispose();
}
}