#c# #asp.net-core #entity-framework-core
#c# #asp.net-core #entity-framework-core
Вопрос:
Я хочу сделать некоторые отчеты в ASP.NET Основной веб-сайт, который считывает данные из нескольких баз данных, используя одну и ту же схему.
В Startup.cs
мне нужно иметь что-то вроде:
public void ConfigureServices(IServiceCollection services)
{
// Some other stuff here.
services.AddDbContext<MyContext>(options => options.UseSqlServer(Configuration.GetConnectionString("FirstConnectionString")));
services.AddDbContext<MyContext>(options => options.UseSqlServer(Configuration.GetConnectionString("SecondConnectionString")));
}
Но теперь DbContext имеют один и тот же тип и не имеют имени, так как же мне выбрать тот, который я хочу использовать в контроллере?
public class HomeController : Controller
{
private readonly MyContext context;
public HomeController(MyContext context)
{
// Is that the one with FirstConnectionString or SecondConnectionString?
// How do I choose?
this.context = context;
}
}
Редактировать:
Возможно, я чего-то не понимаю, но в MyContext
у меня есть:
public class MyContext : DbContext
{
public MyContext(DbContextOptions<MyContext> options) : base(options)
{
}
// Some more code here.
}
Тогда в MyContext1
у меня есть:
public class MyContext1 : MyContext
{
// base in now MyContext and not DbContext !!!
// Error with: public MyContext1(DbContextOptions<MyContext1> options) : base(options)
public MyContext1(DbContextOptions<MyContext> options) : base(options)
{
}
}
Если я добавляю 2 производных типа при запуске и запускаю его, происходит сбой и выдается следующее сообщение об ошибке:
InvalidOperationException: Unable to resolve service for type 'Microsoft.EntityFrameworkCore.DbContextOptions`1[MyContext]' while attempting to activate 'MyContext1'.
Если я также добавлю базовый тип при запуске (таким образом, 3 типа с 3 разными строками подключения), то все 3 типа будут использовать строку подключения базового типа.
Комментарии:
1. Вам придется использовать две контекстные модели. Если схема в точности одинакова, просто создайте 3 класса и сделайте так, чтобы два контекста наследовали класс schema (исходный класс context).
2. Добавил некоторые дополнительные детали к моему ответу, чтобы учесть ваши правки 🙂
Ответ №1:
Почему бы просто не создать два DbContexts? Теоретически, создание 3, вероятно, чище .. сохраните настроенный вами MyContext, а затем просто создайте Db1Context и Db2Context, которые наследуются от него? означает, что ваша регистрация заканчивается как
services.AddDbContext<Db1Context>(options => options.UseSqlServer(Configuration.GetConnectionString("FirstConnectionString")));
services.AddDbContext<Db2Context>(options => options.UseSqlServer(Configuration.GetConnectionString("SecondConnectionString")));
таким образом, его легко решить, и благодаря наследованию вы избегаете некоторого дублирования кода.. но я не вижу никакой пользы от попыток сохранить 1 dbcontext, который передается в несколько db в одном приложении
Редактировать: Если у вас все еще возникают некоторые проблемы с работой DI, на Github был довольно старый поток, который выглядит так, как будто у кого-то была проблема такого типа, которую они решили, выполнив
public class EFDbContext : DbContext
{
public EFDbContext(DbContextOptions<EFDbContext> options) : base(options) { }
protected MainDbContext(DbContextOptions options) : base(options) { }
}
public class DimensionsDbContext : EFDbContext
{
public DimensionsDbContext(DbContextOptions<DimensionsDbContext> options) : base(options) { }
}
что-то в этом роде, имея второй защищенный конструктор в классе, который наследуется от dbcontext, чтобы позволить другим унаследованным классам использовать это. Я имею в виду, я не смог воссоздать проблему со своей стороны, но это решение все еще работает для меня, поэтому может помочь в плане того, чтобы оно работало для вас
Комментарии:
1. Возможно, я что-то упускаю, но просто
DbContextOptions options
не компилируется.2. Очевидно, что это старый вопрос и ответ, но я просто хотел обновить это для людей, которые ищут будущие предложения. Предлагаемая очередь редактирования заполнена, поэтому опубликую здесь: Ошибка с приведенным выше в том, что там написано
protected MainDbContext
, но это должно бытьprotected EFDbContext
Ответ №2:
В конце я создаю несколько контекстов в своих контроллерах отчетов. Это не DI-способ, но он работает.
У меня есть что-то вроде следующего кода в конструкторе контроллера:
var firstOptionsBuilder = new DbContextOptionsBuilder<MyContext>();
firstOptionsBuilder.UseSqlServer("firstConnectionString");
var firstContext = new MyContext(firstOptionsBuilder.Options);