为什么我的上下文在我可以使用它之前就被处理掉了?
Why is my context disposed before I can use it?
我正在 .Net 5 项目中使用 HotChocolate
GraphQL 库实现一个非常简单的查询。我一直在关注 HotChocolate GitHub 存储库中的 tutorial series,但在我的项目中,我不希望 GraphQL 直接访问上下文,而是希望它访问一个存储库,该存储库通过上下文。
我在这个项目中与 GraphQL 一起构建了一些 REST 端点,并且这个存储库模式在那里正常工作。但是,当我从 GraphQL 调用这些存储库方法时,上下文会在存储库方法使用它之前被释放。
我猜测 HotChocolate 使用上下文的方式导致它比我预期的更早被处置,但我无法弄清楚 when/where 它被处置以及如何防止它被处置所以我的存储库方法将起作用。
ContentRepository.cs
namespace BLL.Repository
{
public class ContentRepository : IRepository<Content>
{
private readonly CmsContext _dbContext;
public ContentRepository(CmsContext dbContext)
{
_dbContext = dbContext;
}
public virtual List<Content> GetContent()
{
return _dbContext.Content.ToList();
}
}
}
Query.cs
namespace Web.GraphQL
{
public class Query
{
private readonly IContentRepository _contentRepository;
public Query(IContentRepository contentRepository)
{
_contentRepository = contentRepository;
}
public List<Content> GetContent()
{
return _contentRepository.GetContent() as List<Content>;
}
}
}
Startup.cs
namespace Web
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddControllers().AddNewtonsoftJson();
services.AddDbContext<CmsContext>(options =>
options.UseMySql(Configuration.GetConnectionString("DefaultConnection"), ServerVersion.AutoDetect(Configuration.GetConnectionString("DefaultConnection"))));
services
.AddGraphQLServer()
.ModifyRequestOptions(options => options.IncludeExceptionDetails = true)
.AddQueryType<Query>();
services.AddScoped<IRepository<Content>, ContentRepository>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
if (env.IsDevelopment()) app.UseDeveloperExceptionPage();
app.UseHttpsRedirection();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute("default", "/{controller}/{action}",
new {controller = "Default", action = "Index"});
});
app.UseEndpoints(endpoints => endpoints.MapGraphQL());
app.UseGraphQLVoyager(new VoyagerOptions
{
GraphQLEndPoint = "/graphql"
}, "/graphql-voyager");
}
}
}
调试和单步执行代码时,一旦到达 ContentRepository.cs
中的 GetContent
方法,它就会抛出一个 ObjectDisposedException
.
当从 GraphQL 查询调用时,我需要做什么来确保 CmsContext
对 ContentRepository
仍然可用?
只能使用构造函数注入with HotChocolate v11:
services
.AddScoped<IUserRepository, UserRepository>()
.AddScoped<Query>()
.AddGraphQLServer()
.AddQueryType<Query>()
public class Query
{
public Query(IUserRepository repository)
{
}
// code omitted for brevity
}
如果您使用的是 HotChocolate v10,您需要 use parameter injection 和 [Service]
属性:
public class Query
{
public string Bar(ISchema schema, [Service]MyCustomService service)
{
return "foo";
}
}
参考资料
根据文档,在构造函数中,您还可以获得这样的服务:
public class Query
{
private readonly IEntityRepository _entityRepository;
public Query([Service] IEntityRepository entityRepository)
{
_entityRepository= entityRepository;
}
public IQueryable<Entity> Entities=> _entityRepository.GetAll();
}
我正在 .Net 5 项目中使用 HotChocolate
GraphQL 库实现一个非常简单的查询。我一直在关注 HotChocolate GitHub 存储库中的 tutorial series,但在我的项目中,我不希望 GraphQL 直接访问上下文,而是希望它访问一个存储库,该存储库通过上下文。
我在这个项目中与 GraphQL 一起构建了一些 REST 端点,并且这个存储库模式在那里正常工作。但是,当我从 GraphQL 调用这些存储库方法时,上下文会在存储库方法使用它之前被释放。
我猜测 HotChocolate 使用上下文的方式导致它比我预期的更早被处置,但我无法弄清楚 when/where 它被处置以及如何防止它被处置所以我的存储库方法将起作用。
ContentRepository.cs
namespace BLL.Repository
{
public class ContentRepository : IRepository<Content>
{
private readonly CmsContext _dbContext;
public ContentRepository(CmsContext dbContext)
{
_dbContext = dbContext;
}
public virtual List<Content> GetContent()
{
return _dbContext.Content.ToList();
}
}
}
Query.cs
namespace Web.GraphQL
{
public class Query
{
private readonly IContentRepository _contentRepository;
public Query(IContentRepository contentRepository)
{
_contentRepository = contentRepository;
}
public List<Content> GetContent()
{
return _contentRepository.GetContent() as List<Content>;
}
}
}
Startup.cs
namespace Web
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddControllers().AddNewtonsoftJson();
services.AddDbContext<CmsContext>(options =>
options.UseMySql(Configuration.GetConnectionString("DefaultConnection"), ServerVersion.AutoDetect(Configuration.GetConnectionString("DefaultConnection"))));
services
.AddGraphQLServer()
.ModifyRequestOptions(options => options.IncludeExceptionDetails = true)
.AddQueryType<Query>();
services.AddScoped<IRepository<Content>, ContentRepository>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
if (env.IsDevelopment()) app.UseDeveloperExceptionPage();
app.UseHttpsRedirection();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute("default", "/{controller}/{action}",
new {controller = "Default", action = "Index"});
});
app.UseEndpoints(endpoints => endpoints.MapGraphQL());
app.UseGraphQLVoyager(new VoyagerOptions
{
GraphQLEndPoint = "/graphql"
}, "/graphql-voyager");
}
}
}
调试和单步执行代码时,一旦到达 ContentRepository.cs
中的 GetContent
方法,它就会抛出一个 ObjectDisposedException
.
当从 GraphQL 查询调用时,我需要做什么来确保 CmsContext
对 ContentRepository
仍然可用?
只能使用构造函数注入with HotChocolate v11:
services
.AddScoped<IUserRepository, UserRepository>()
.AddScoped<Query>()
.AddGraphQLServer()
.AddQueryType<Query>()
public class Query
{
public Query(IUserRepository repository)
{
}
// code omitted for brevity
}
如果您使用的是 HotChocolate v10,您需要 use parameter injection 和 [Service]
属性:
public class Query
{
public string Bar(ISchema schema, [Service]MyCustomService service)
{
return "foo";
}
}
参考资料
根据文档,在构造函数中,您还可以获得这样的服务:
public class Query
{
private readonly IEntityRepository _entityRepository;
public Query([Service] IEntityRepository entityRepository)
{
_entityRepository= entityRepository;
}
public IQueryable<Entity> Entities=> _entityRepository.GetAll();
}