Правильный способ получения DbContext в реализации сервиса gRPC

#c# #entity-framework #grpc

#c# #entity-framework #grpc

Вопрос:

Различные онлайн-примеры показывают внедрение DbContext в службу gRPC в конструкторе службы:

 public ImageStorageService(ILogger<ImageStorageService> logger, SqliteDbContext dbContext)
{
    _logger = logger;
    _dbContext = dbContext;
}
  

и использовать этот _dbContext во всех методах реализации gRPC. Это не кажется правильным — я новичок в EF и .Net Core web в целом, но DbContext не является потокобезопасным, и несколько методов gRPC могут выполняться одновременно, да?

В любом случае я нашел другой способ, вот конструктор и пример реализации метода api:

 public ImageStorageService(ILogger<ImageStorageService> logger, IServiceScopeFactory serviceScopeFactory)
{
    _logger = logger;
    _serviceScopeFactory = serviceScopeFactory;
}

public override async Task<GetImageCountReply> GetImageCount(GetImageCountRequest request, ServerCallContext context)
{
    using var scope = _serviceScopeFactory.CreateScope();
    var dbContext = scope.ServiceProvider.GetRequiredService<SqliteDbContext>();
    var count = await dbContext.StoredImages.CountAsync(context.CancellationToken);
    return new GetImageCountReply { Count = count };
}
  

Я слишком усложняю ситуацию? Услуги.AddDbContext<> вводит контексты базы данных с ограниченным временем жизни, так что это необходимо, не так ли?

Комментарии:

1. Я считаю, что ничто не сравнится с обычной формой using(SqliteDbContext DbContext = new SqliteDbContext()) . Причина, по которой я не внедряю DbContext в свой собственный код, заключается в том, что я сохраняю инъекции, зарезервированные для интерфейсов, а не для конкретных классов (хотя это не абсолютное правило). В вашем примере, когда вы запрашиваете DbContext, вы указываете тип DbContext, который вам нужен, так зачем вам понадобилось дополнительное оборудование для его создания? Это потому, что вы передаете параметры конструктору DbContext ?

2. Использование простого инжектора позволяет использовать встроенные функции, такие как AddDbContextPool, когда этого требует производительность, например. Я думаю, что использование инъекции является предпочтительным способом.