ObjectDisposedException 尝试实施 DDD 项目
ObjectDisposedException trying implement DDD project
当我尝试 return 我的 orderList 作为 IQueryable 时,我收到以下错误:
"ObjectDisposedException: 无法访问已处置的对象。导致此错误的一个常见原因是处置从依赖项注入解析的上下文,然后尝试在应用程序的其他位置使用相同的上下文实例。如果您在上下文中调用 Dispose(),或者将上下文包装在 using 语句中。如果您使用依赖注入,则应该让依赖注入容器负责处理上下文实例。
对象名称:'KeplerContext'"
Ps。如果我直接在我的控制器上使用 DbContext,一切正常。
有帮助吗?提前致谢。
我的控制器 class 是:
public class OrderController : Controller
{
public readonly IAppOrder _IAppOrder;
public readonly UserManager<User> _userManager;
// Ps.: Directly for the context works fine
//private readonly KeplerContext _context;
public OrderController(IAppOrder IAppOrder, UserManager<User> userManager) //, KeplerContext context)
{
_IAppOrder = IAppOrder;
_userManager = userManager;
// Ps.: Directly for the context works fine
//_context = context;
}
public async Task<IActionResult> Index(string sortOrder, int? pageNumber)
{
var user = await _userManager.GetUserAsync(User);
var orderList = _IAppOrder.OrderList(user);
^^^^
if (!orderList.Any())
{
TempData["info"] = "no orders.";
}
else
{
var orderActive = await _IAppOrder.GetLastOrder(user);
if (orderActive.IdOrderStatus <= 5)
{
return RedirectToAction(nameof(OrderController.Order), "Order", new { Area = "App", Id = orderActive.IdOrder });
}
}
// paging
ViewData["CurrentSort"] = sortOrder;
ViewData["NumSort"] = String.IsNullOrEmpty(sortOrder) ? "num_asc" : "";
switch (sortOrder)
{
case "num_asc":
orderList = orderList.OrderBy(s => s.IdOrder);
break;
default:
orderList = orderList.OrderByDescending(s => s.IdOrder);
break;
}
int pageSize = 8;
return View(await PagingHelper<Order>.CreateAsync(orderList.AsNoTracking(), pageNumber ?? 1, pageSize));
}
}
我的申请class:(Ps。我正在使用DDD,其他人class我已经省略以简化问题):
public IQueryable<Order> OrderList (User user)
{
return _IOrder.OrderList(user);
}
我的仓库class:
public class RepositoryOrder : RepositoryGenerics<Order>, IDomOrder
{
private readonly DbContextOptions<KeplerContext> _optionsBuilder;
public RepositoryOrder()
{
_optionsBuilder = new DbContextOptions<KeplerContext>();
}
public IQueryable<Order> OrderList(User user)
{
using var db = new DbContext(_optionsBuilder);
var result = db.Order
.Include(p => p.IdOrderStatusNavigation)
.Include(p => p.IdNavigation)
.Where(u => u.Id == user.Id)
.AsQueryable();
return result;
^^^^^^ <<< Error happens here!!!
}
}
我的存储库泛型 class:
public class RepositoryGenerics<T> : IDomGeneric<T>, IDisposable where T : class
{
private readonly DbContextOptions<KeplerContext> _OptionsBuilder;
public RepositoryGenerics()
{
_OptionsBuilder = new DbContextOptions<KeplerContext>();
}
public async Task Add(T obj)
{
using var data = new KeplerContext(_OptionsBuilder);
await data.Set<T>().AddAsync(obj);
await data.SaveChangesAsync();
}
public async Task Delete(T obj)
{
using var data = new KeplerContext(_OptionsBuilder);
data.Set<T>().Remove(obj);
await data.SaveChangesAsync();
}
public async Task<T> GetEntityById(int Id)
{
using var data = new KeplerContext(_OptionsBuilder);
return await data.Set<T>().FindAsync(Id);
}
public async Task<List<T>> List()
{
using var data = new KeplerContext(_OptionsBuilder);
return await data.Set<T>().AsNoTracking().ToListAsync();
}
public async Task Update(T obj)
{
using var data = new KeplerContext(_OptionsBuilder);
data.Set<T>().Update(obj);
await data.SaveChangesAsync();
}
// https://docs.microsoft.com/pt-br/dotnet/standard/garbage-collection/implementing-dispose
bool disposed = false;
SafeHandle handle = new SafeFileHandle(IntPtr.Zero, true);
// "Dispose Pattern"
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
handle.Dispose();
}
disposed = true;
}
}
Startup.cs 内的依赖注入:
// Repository
services.AddSingleton(typeof(IDomGeneric<>), typeof(RepositoryGenerics<>));
...
services.AddSingleton<IDomOrder, RepositoryOrder>();
...
// Inteface da Application
...
services.AddSingleton<IAppOrder, AppOrder>();
...
// Service Domain
...
services.AddSingleton<IServiceOrder, ServiceOrder>();
...
您的 RepositoryOrder.OrderList
正在返回 IQueryable
,这意味着您 未 在该方法的范围内执行查询。所以我相信您所看到的是,当最终执行查询时,DbContext
已经被处理掉了,因为一旦您离开方法范围,它就会被处理掉。
您可以调用 ToList
而不是 AsQueryable
。
当我尝试 return 我的 orderList 作为 IQueryable 时,我收到以下错误:
"ObjectDisposedException: 无法访问已处置的对象。导致此错误的一个常见原因是处置从依赖项注入解析的上下文,然后尝试在应用程序的其他位置使用相同的上下文实例。如果您在上下文中调用 Dispose(),或者将上下文包装在 using 语句中。如果您使用依赖注入,则应该让依赖注入容器负责处理上下文实例。 对象名称:'KeplerContext'"
Ps。如果我直接在我的控制器上使用 DbContext,一切正常。
有帮助吗?提前致谢。
我的控制器 class 是:
public class OrderController : Controller
{
public readonly IAppOrder _IAppOrder;
public readonly UserManager<User> _userManager;
// Ps.: Directly for the context works fine
//private readonly KeplerContext _context;
public OrderController(IAppOrder IAppOrder, UserManager<User> userManager) //, KeplerContext context)
{
_IAppOrder = IAppOrder;
_userManager = userManager;
// Ps.: Directly for the context works fine
//_context = context;
}
public async Task<IActionResult> Index(string sortOrder, int? pageNumber)
{
var user = await _userManager.GetUserAsync(User);
var orderList = _IAppOrder.OrderList(user);
^^^^
if (!orderList.Any())
{
TempData["info"] = "no orders.";
}
else
{
var orderActive = await _IAppOrder.GetLastOrder(user);
if (orderActive.IdOrderStatus <= 5)
{
return RedirectToAction(nameof(OrderController.Order), "Order", new { Area = "App", Id = orderActive.IdOrder });
}
}
// paging
ViewData["CurrentSort"] = sortOrder;
ViewData["NumSort"] = String.IsNullOrEmpty(sortOrder) ? "num_asc" : "";
switch (sortOrder)
{
case "num_asc":
orderList = orderList.OrderBy(s => s.IdOrder);
break;
default:
orderList = orderList.OrderByDescending(s => s.IdOrder);
break;
}
int pageSize = 8;
return View(await PagingHelper<Order>.CreateAsync(orderList.AsNoTracking(), pageNumber ?? 1, pageSize));
}
}
我的申请class:(Ps。我正在使用DDD,其他人class我已经省略以简化问题):
public IQueryable<Order> OrderList (User user)
{
return _IOrder.OrderList(user);
}
我的仓库class:
public class RepositoryOrder : RepositoryGenerics<Order>, IDomOrder
{
private readonly DbContextOptions<KeplerContext> _optionsBuilder;
public RepositoryOrder()
{
_optionsBuilder = new DbContextOptions<KeplerContext>();
}
public IQueryable<Order> OrderList(User user)
{
using var db = new DbContext(_optionsBuilder);
var result = db.Order
.Include(p => p.IdOrderStatusNavigation)
.Include(p => p.IdNavigation)
.Where(u => u.Id == user.Id)
.AsQueryable();
return result;
^^^^^^ <<< Error happens here!!!
}
}
我的存储库泛型 class:
public class RepositoryGenerics<T> : IDomGeneric<T>, IDisposable where T : class
{
private readonly DbContextOptions<KeplerContext> _OptionsBuilder;
public RepositoryGenerics()
{
_OptionsBuilder = new DbContextOptions<KeplerContext>();
}
public async Task Add(T obj)
{
using var data = new KeplerContext(_OptionsBuilder);
await data.Set<T>().AddAsync(obj);
await data.SaveChangesAsync();
}
public async Task Delete(T obj)
{
using var data = new KeplerContext(_OptionsBuilder);
data.Set<T>().Remove(obj);
await data.SaveChangesAsync();
}
public async Task<T> GetEntityById(int Id)
{
using var data = new KeplerContext(_OptionsBuilder);
return await data.Set<T>().FindAsync(Id);
}
public async Task<List<T>> List()
{
using var data = new KeplerContext(_OptionsBuilder);
return await data.Set<T>().AsNoTracking().ToListAsync();
}
public async Task Update(T obj)
{
using var data = new KeplerContext(_OptionsBuilder);
data.Set<T>().Update(obj);
await data.SaveChangesAsync();
}
// https://docs.microsoft.com/pt-br/dotnet/standard/garbage-collection/implementing-dispose
bool disposed = false;
SafeHandle handle = new SafeFileHandle(IntPtr.Zero, true);
// "Dispose Pattern"
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
handle.Dispose();
}
disposed = true;
}
}
Startup.cs 内的依赖注入:
// Repository
services.AddSingleton(typeof(IDomGeneric<>), typeof(RepositoryGenerics<>));
...
services.AddSingleton<IDomOrder, RepositoryOrder>();
...
// Inteface da Application
...
services.AddSingleton<IAppOrder, AppOrder>();
...
// Service Domain
...
services.AddSingleton<IServiceOrder, ServiceOrder>();
...
您的 RepositoryOrder.OrderList
正在返回 IQueryable
,这意味着您 未 在该方法的范围内执行查询。所以我相信您所看到的是,当最终执行查询时,DbContext
已经被处理掉了,因为一旦您离开方法范围,它就会被处理掉。
您可以调用 ToList
而不是 AsQueryable
。