提问人:Brett JB 提问时间:11/16/2023 最后编辑:Brett JB 更新时间:11/17/2023 访问量:59
实体框架 无法访问已释放的上下文实例 - 但工作方式是从外部控制器调用的
Entity Framework Cannot access a disposed context instance - but works called from external controller
问:
在控制器中处理交易时,我在“accountsHelpers”库中有一个函数,用于将付款标记为已付款。控制器越来越重,所以我在“accountsHelpers”中创建了一个“processReceipt”函数来保持控制器的轻量级。这是学术性的,但提供了一个背景。
在帮助程序中创建“processReceipt”函数后,我看到它不再起作用,因为当它在同一帮助程序库中调用“MarkTransactionAsPaid”函数时,我收到此错误:
System.ObjectDisposedException HResult=0x80131622 Message=无法访问已释放的上下文实例。此错误的常见原因是释放从依赖项注入解析的上下文实例,然后尝试在应用程序的其他位置使用相同的上下文实例。如果在上下文实例上调用“Dispose”,或将其包装在 using 语句中,则可能会发生这种情况。如果使用依赖项注入,则应让依赖项注入容器负责处理上下文实例。
这有点奇怪,因为我修改了函数,除了查找对象并保存更改之外什么都不做......喜欢这个:
public async Task<InfoBool> MarkTransactionAsPaid(
int paymentId, string pspReference, string receiptId)
{
try
{
MoneyTransaction? foundtransaction =
await _context.MoneyTransactions
.Where(p => p.Id == paymentId)
.Include(p =>p.User)
.FirstOrDefaultAsync();
... // do stuff
await _context.SaveChangesAsync();
交易被发现很好,但是即使我删除了所有“做事”代码,SaveShanges也立即导致错误......
我在这里看到了对此的各种引用,大多数解决方案似乎都可以通过缺少“await”或函数在异步时返回 Void 来解决......我不认为这是这里的问题,也许围绕着我对依赖注入的理解(或缺乏)。
这是调用代码:
try
{
if (receipt.result == "Success")
{
if (string.IsNullOrEmpty(receipt.originalReceiptId)) // Then this is a payment
{
var paymentId = int.Parse(receipt.consumer.yourConsumerReference);
InfoBool res = await _accountsHelpers.MarkTransactionAsPaid(paymentId, receipt.yourPaymentReference, receipt.receiptId);
if (!res.Success)
{
... etc
在我的 accountsHelpers 中,我注入了 DBContext,如下所示:(略有简化)
public AccountsHelpers(
IMapper mapper,
RGDbContext context,
IConfiguration settings,
IAzureHelpers azureHelpers)
public AccountsHelpers(
IMapper mapper,
RGDbContext context,
IConfiguration settings,
IAzureHelpers azureHelpers)
{
_mapper = mapper;
_context = context;
_settings = settings;
_logger = logger;
_azureHelpers = azureHelpers;
}
在我的程序.cs中,并添加帐户助手,如下所示:
//AccountsHelpers
builder.Services.AddScoped<IAccountsHelpers, AccountsHelpers>();
以前,我在控制器中处理收据处理,从那里调用函数时,它工作正常。
InfoBool res = await _accountsHelpers.MarkTransactionAsPaid(
paymentId,
paymentResult.receipt.yourPaymentReference,
paymentResult.receipt.receiptId);
if (!res.Success)...
我不清楚我在哪里调用“处置”,我确实想知道它是否可能是两个函数中的 try catch 块?但不要真正看到这一点。还想知道这是否是我设置 DI 的方式......
我现在已经通过将函数移回控制器来解决这个问题......但我想理解这一点,而且,代码对于控制器来说真的有点太重了。有什么想法吗?ProcessReceipt
答: 暂无答案
评论
MarkTransactionAsPaid
SaveChangesAsync
DbContext
await
IQueryable/IEnumerable