C# Asp.net core:无法访问已释放的对象。此错误的一个常见原因是处理依赖项注入解析的上下文
我正在开发一个web api项目。现在,我在调用端点时遇到了一个问题。我在调用此端点时不会经常出错,例如,如果我每天调用30次,则会出现2次此错误。此端点仅选择数据并异步工作。我尝试了在互联网上找到的所有解决方案,但都不起作用。 错误:无法访问已释放的对象。此错误的一个常见原因是处理通过依赖项注入解析的上下文,然后在应用程序的其他位置尝试使用相同的上下文实例。如果对上下文调用Dispose(),或将上下文包装到using语句中,则可能会发生这种情况。如果您使用的是依赖项注入,那么应该让依赖项注入容器处理上下文实例C# Asp.net core:无法访问已释放的对象。此错误的一个常见原因是处理依赖项注入解析的上下文,c#,entity-framework,asp.net-core,dependency-injection,C#,Entity Framework,Asp.net Core,Dependency Injection,我正在开发一个web api项目。现在,我在调用端点时遇到了一个问题。我在调用此端点时不会经常出错,例如,如果我每天调用30次,则会出现2次此错误。此端点仅选择数据并异步工作。我尝试了在互联网上找到的所有解决方案,但都不起作用。 错误:无法访问已释放的对象。此错误的一个常见原因是处理通过依赖项注入解析的上下文,然后在应用程序的其他位置尝试使用相同的上下文实例。如果对上下文调用Dispose(),或将上下文包装到using语句中,则可能会发生这种情况。如果您使用的是依赖项注入,那么应该让依赖项注入
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<MyContext>(options => options.UseMySql(Environment.GetEnvironmentVariable("MY_DB_CONNECTION")), ServiceLifetime.Transient);
services.DIRegisterer();
}
public static IServiceCollection DIRegisterer(this IServiceCollection services)
{
services.AddScoped<MyService>();
}
public void配置服务(IServiceCollection服务)
{
services.AddDbContext(options=>options.UseMySql(Environment.GetEnvironmentVariable(“MY_DB_CONNECTION”))、ServiceLifetime.Transient);
services.diregister();
}
公共静态IServiceCollection diregister(此IServiceCollection服务)
{
services.addScope();
}
注意:我使用的是.NETCore3.1
--更新
从日志中可以看出,ResponseWrapperFilter类导致了此错误。但由于调试时无法捕获此错误,因此找不到原因
public class ResponseWrapperFilter : IActionFilter, IOrderedFilter
{
private MYContext myContext;
private IMemoryCache cache;
private readonly TimeSpan _defaultCacheTimespan = new TimeSpan(0, 5, 0);
private void FillNavigationProperties(object v, int recursionLevel)
{
if (recursionLevel > 2)
return;
if (v.GetType().FullName == "System.DateTime" || v.GetType().FullName == "System.String"
|| v.GetType().FullName == "Newtonsoft.Json.Linq.JObject")
return;
if (v != null && v.GetType().FullName.StartsWith("System.Collections.Generic.List"))
{
foreach (var x in (IList)v)
{
foreach (var y in x.GetType().GetProperties())
{
if (x.GetType().FullName == "System.DateTime" || x.GetType().FullName == "System.String"
|| x.GetType().FullName == "Newtonsoft.Json.Linq.JObject")
continue;
var prop = y.GetGetMethod().Invoke(x, null);
if (prop != null)
{
FillNavigationProperties(prop, recursionLevel + 1);
}
else
{
TryToFillNavigationProperty(x, y);
}
}
}
}
}
private void TryToFillNavigationProperty(object v, PropertyInfo p)
{
if (p.PropertyType == typeof(Company) || p.PropertyType.IsSubclassOf(typeof(Company)))
{
if (v.GetType().GetProperties().Where(_ => _.Name == p.Name + "Id").Any())
{
var CompanyId = (ulong)v.GetType().GetProperties().Where(_ => _.Name == p.Name + "Id").First().GetGetMethod().Invoke(v, null);
var cacheKey = "Company->Id->" + CompanyId.ToString();
if (cache.TryGetValue(cacheKey, out Company CompanyIdCompany))
{
p.GetSetMethod().Invoke(v, new[] { CompanyIdCompany });
}
else
{
CompanyIdCompany = myContext.Set<Company>().Where(_ => _.Id == CompanyId).FirstOrDefault();
cache.Set(cacheKey, CompanyIdCompany, _defaultCacheTimespan);
**p.GetSetMethod().Invoke(v, new[] { CompanyIdCompany });**
}
}
}
}
public void OnActionExecuted(ActionExecutedContext context)
{
if (context.Exception is null)
{
myContext = context.HttpContext.RequestServices.GetRequiredService<MYContext>();
cache = context.HttpContext.RequestServices.GetRequiredService<IMemoryCache>();
if (context.Result.GetType() == typeof(ObjectResult))
{
object current = ((ObjectResult)context.Result).Value;
if (current != null)
FillNavigationProperties(current, 0);
context.Result = new OkObjectResult(new MYResponse()
{
Data = current
});
}
}
}
}
public类ResponseWrapperFilter:IActionFilter、IOrderedFilter
{
私有MYContext MYContext;
私有IMemoryCache缓存;
private readonly TimeSpan _defaultCacheTimespan=new TimeSpan(0,5,0);
私有void FillNavigationProperties(对象v,int递归级别)
{
如果(递归级别>2)
返回;
如果(v.GetType().FullName==“System.DateTime”| | v.GetType().FullName==“System.String”
||v.GetType().FullName==“Newtonsoft.Json.Linq.JObject”)
返回;
if(v!=null&&v.GetType().FullName.StartsWith(“System.Collections.Generic.List”))
{
foreach(var x in(IList)v)
{
foreach(x.GetType().GetProperties()中的变量y)
{
如果(x.GetType().FullName==“System.DateTime”| | x.GetType().FullName==“System.String”
||x.GetType().FullName==“Newtonsoft.Json.Linq.JObject”)
继续;
var prop=y.getMethod().Invoke(x,null);
如果(prop!=null)
{
FillNavigationProperties(prop,recursionLevel+1);
}
其他的
{
TryToFillNavigationProperty(x,y);
}
}
}
}
}
私有void TryToFillNavigationProperty(对象v,PropertyInfo p)
{
如果(p.PropertyType==typeof(Company)| | p.PropertyType.IsSubclassOf(typeof(Company)))
{
if(v.GetType().GetProperties().Where(\u=>\ uName==p.Name+“Id”).Any())
{
var CompanyId=(ulong)v.GetType().GetProperties().Where(\u=>\ uName==p.Name+“Id”).First().getMethod().Invoke(v,null);
var cacheKey=“Company->Id->”+CompanyId.ToString();
if(cache.TryGetValue(cacheKey,out Company Company))
{
p、 GetSetMethod().Invoke(v,new[]{CompanyIdCompany});
}
其他的
{
CompanyIdCompany=myContext.Set().Where(=>u.Id==CompanyId.FirstOrDefault();
Set(cacheKey,CompanyIdCompany,\u defaultCacheTimespan);
**p、 GetSetMethod().Invoke(v,new[]{CompanyIdCompany})**
}
}
}
}
public void OnActionExecuted(ActionExecutedContext上下文)
{
if(context.Exception为null)
{
myContext=context.HttpContext.RequestServices.GetRequiredService();
cache=context.HttpContext.RequestServices.GetRequiredService();
if(context.Result.GetType()==typeof(ObjectResult))
{
对象当前=((ObjectResult)context.Result).Value;
如果(当前!=null)
FillNavigationProperties(当前,0);
context.Result=new-OkObjectResult(new-MYResponse()
{
数据=当前
});
}
}
}
}
据我从日志中看到的,粗体行是导致错误的原因(p.GetSetMethod().Invoke(v,new[]{CompanyIdCompany});)因为这个问题只是偶尔出现,问题的一个可能原因是(意外)与请求操作并行运行的生成后台操作。此并行操作可以访问请求的
DbContext
实例
注意:如果错误在初始成功操作后仍然存在,这将表示DbContext
被其一个使用者捕获;换言之,这是一个错误
在大多数情况下,后台操作在请求结束之前完成,因此在处置DbContext
之前完成。但是,在某些情况下,(意外)并行操作会出现延迟,导致它在请求结束后访问DbContext
,从而在ASP.NET内核处理DbContext
后访问
这可能是因为您忘记等待一个异步操作。当您忘记等待此类操作时,它将开始并行运行。然而,并行运行这样的代码通常是有益的