[英]Generic DBContext Injection with Autofac
我正在嘗試通過 Autofac 將 DbContext 實例注冊並注入到我的組件中。 我知道我目前使用的方法可以改進,我也在尋找如何實現這一目標的想法。 目前我只是在玩通用的想法並試圖讓它工作,但它拋出了這個異常。 Autofac 是否有可能產生多個線程來注入組件?
System.Threading.Tasks.TaskCanceledException: A task was canceled.
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenDbConnectionAsync(Boolean errorsExpected, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenDbConnectionAsync(Boolean errorsExpected, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenAsync(CancellationToken cancellationToken, Boolean errorsExpected)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.AsyncEnumerator.InitializeReaderAsync(DbContext _, Boolean result, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleOrDefaultAsync[TSource](IAsyncEnumerable`1 asyncEnumerable, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleOrDefaultAsync[TSource](IAsyncEnumerable`1 asyncEnumerable, CancellationToken cancellationToken)
at UserService.Repositories.UserRepository.FindByIdAsync(String id) in /Users/ryanr/Documents/invoicer-backend-microservices/src/UserService/Repositories/UserRepository.cs:line 31
at UserService.Queries.Handlers.GetUserByIDQueryHandler.Handle(GetUserByIDQuery query) in /Users/ryanr/Documents/invoicer-backend-microservices/src/UserService/Queries/Handlers/GetUserByIDQueryHandler.cs:line 19
at UserService.Controllers.UsersController.GetUserById(GetUserByIDQuery query) in /Users/ryanr/Documents/invoicer-backend-microservices/src/UserService/Controllers/UsersController.cs:line 43
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
我有一個類庫,用於注冊 Autofac 類型並定義 DBContext 接口:
public interface IDbContext<T> where T: class
{
DbSet<T> DataSet { get; set; }
}
用於注冊存儲庫和注入 DbContext 的 Autofac 模塊
public class RepositoryModule : Autofac.Module
{
public Assembly ExecutingAssembly { get; set; }
public string ConnectionString { get; set; }
protected override void Load(ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(ExecutingAssembly)
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces();
builder.RegisterAssemblyTypes(ExecutingAssembly)
.Where(t => t.IsClosedTypeOf(typeof(IDbContext<>)))
.AsSelf()
.InstancePerLifetimeScope();
}
}
然后得到解決並注入到我的 UserService(ASP.Net) 中:
public class UserRepository : IUserRepository
{
private readonly UserDBContext _dbContext;
public UserRepository(UserDBContext dbContext)
{
_dbContext = dbContext;
}
public async Task<User> FindByIdAsync(string id)
{
return await _dbContext.DataSet.FirstOrDefaultAsync(user => user.Id == id);
}
}
DbContext 類
public class UserDBContext : DbContext, IDbContext<User>
{
public DbSet<User> DataSet { get; set; }
public UserDBContext()
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("server=localhost,1434;user id=sa;password=password;database=UserManagement;");
}
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<User>().HasKey(m => m.Id);
builder.Entity<User>().ToTable("User");
base.OnModelCreating(builder);
}
}
然后將存儲庫注入到我的 QueryHandler 中,這就是使用 DBContext 的地方:
public class GetUserByIDQueryHandler : IQueryHandler<GetUserByIDQuery, User>
{
private IUserRepository _repository;
public GetUserByIDQueryHandler(IUserRepository repository)
{
_repository = repository;
}
public async Task<User> Handle(GetUserByIDQuery query)
{
return await _repository.FindByIdAsync(query.Id);
}
}
QueryHandlers 的解析方式如下:
var handlers = scope.Resolve<IEnumerable<IQueryHandler<TRequest, TResponse>>>().ToList();
編輯:我有理由相信這是一個依賴注入/一個 Autofac 問題,因為這個微不足道的測試最終成功了:
// GET api/users/5
[HttpGet("{Id}", Name = "GetUserById")]
public async Task<IActionResult> GetUserById([FromBody]GetUserByIDQuery query)
{
//var users = await _queryBus.Query<GetUserByIDQuery, User>(query);
//string id = new Guid().ToString();
//var users = await _dbContext.DataSet.FirstOrDefaultAsync(x => x.Id == id);
using(var dbContext = new UserDBContext())
{
return Ok(await dbContext.DataSet.ToListAsync());
}
}
任何幫助,將不勝感激! 謝謝 :)
我認為這與依賴注入或 autofac 沒有任何關系。 看看堆棧跟蹤——跟蹤的頂部說:
在 Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenDbConnectionAsync(布爾錯誤預期,CancellationToken 取消令牌)
這看起來像連接到數據庫的問題。 檢查您的連接字符串並進行快速測試,以確保您可以連接到數據庫,而沒有 autofac 或查詢處理程序的復雜性開銷。
我解決了這個問題。
QueryHandler 試圖同步解析異步函數,但它導致了問題。
例如:
var handlers = scope.Resolve<IEnumerable<IQueryHandler<TRequest, TResponse>>>().ToList();
return await handlers[0].Handle(query);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.