[英]ASP.NET Boilerplate - “The ObjectContext instance has been disposed” exception
我正在嘗試使用ASP.NET Boilerplate處理我的項目,但我遇到了一個嚴重的問題。
我有2個模特:照片和評論:
public class Comment : Entity<int>
{
[DataType(DataType.MultilineText)]
public string Text { get; set; }
public string Author { get; set; }
public int ItemID { get; set; }
public virtual Item Item { get; set; }
}
public class Item : Entity<int>
{
public string Title { get; set; }
public string Description { get; set; }
public ItemSourceType SourceType { get; set; }
public byte[] PhotoBytes { get; set; }
public string Url { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
}
另外,我已經基於RepositoryBase<Item>
創建了默認的OOB存儲庫,並且對Comment
。
當我嘗試獲得像這樣的商品時,存在問題:
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Item item = _repoItems.Get(id.Value);
if (item == null)
{
return HttpNotFound();
}
return View(item);
}
當我調試此代碼時,我可以在Comments
屬性中看到該item
具有此異常。
我是否缺少ASP.NET Boilerplate的內容?
感謝您的幫助!
//編輯:完整的異常消息:
{"The ObjectContext instance has been disposed and can no longer be used for operations that require a connection."}
我只是偶然發現了同樣的問題。 似乎是UnitOfWork實現為每個“ UnitOfWork”創建並布置了一個新的DbContext。
因此,要解決該特定問題,請嘗試注入“ IUnitOfWorkManager”並調用
public ActionResult Details(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } using(var uow = _unitOfWorkManager.Begin()) { try { Item item = _repoItems.Get(id.Value); if (item == null) { return HttpNotFound(); } return View(item); } finally { uow.Complete() }; } }
如果可行,請考慮在ApiController的構造函數中調用“ Begin()”,並在其“ Dispose()”替代中調用“ Complete()”。 希望有幫助!
否。問題很可能在您的存儲庫中,不幸的是您未包含其中的代碼。 如果我不得不猜測,我會說您在該存儲庫方法中使用的是以下內容:
using (var context = new ApplicationContext())
{
// fetch something
}
您的Comments
屬性是虛擬的,這意味着默認情況下,Entity Framework將延遲加載它,僅當您嘗試訪問該屬性時才向數據庫實際發出該查詢。 但是,到那時,您的上下文已被處置,因為存儲庫方法已完成其工作,並且您的上下文僅在using
塊內可用。
有很多方法可以解決此問題。 您可以熱切地在using塊中加載注釋:
return context.Items.Include("Comments").Find(id);
但是,這確實可以解決問題。 您可以做的最好的事情就是不使用using
。 理想情況下,對於每個請求,您的上下文應實例化一次,並且只能實例化一次。 最簡單的方法是使用依賴項注入容器,並向您的存儲庫中添加一個接受上下文的構造函數:
public class MyAwesomeRepository
{
private readonly ApplicationContext context;
public MyAwesomeRepository(ApplicationContext context)
{
this.context = context;
}
}
DI容器的配置將根據您選擇的配置而有所不同,但是通常,您需要確保將上下文類綁定到請求范圍。
我在ASP.NET Boilerplate中遇到了類似的問題,並發現只有當您根據接口和類的命名約定命名該接口和類時,此框架才能正確實現所有DI魔術。 您可以通過某種方式手動進行操作,但是您必須深入了解ABP架構,而不是想要的。
@ChrisPratt發布的鏈接(請參閱答案中的評論)說:
命名約定在這里非常重要。 例如,您可以將PersonAppService的名稱更改為MyPersonAppService或其他包含“ PersonAppService”后綴的名稱,因為IPersonAppService具有此后綴。 但是您不能將服務命名為PeopleService。 如果執行此操作,則不會自動為IPersonAppService注冊(它已注冊到DI框架,但已通過自注冊,而不是通過接口注冊),因此,如果需要,應手動注冊。
就我而言,我有一個名為ProductService的服務,該服務實現了IProductAppService接口。 在我將服務重命名為ProductAppService之前,它因ObjectDisposedException異常而失敗。
我認為OP仍然沒有這個問題,但是希望它將為像我一樣在ABP方面苦苦掙扎的人們節省幾個小時。 :-)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.