Запуск каркаса DbContext без перезаписи пользовательского кода в ядре Entity Framework

#c# #entity-framework-core #dbcontext

#c# #entity-framework-core #dbcontext

Вопрос:

Я использую EF Core и DB First подход. Я создаю свой класс DbContext и entities, используя Scaffold-DbContext , и это дало мне ожидаемый результат, но когда я Scaffold-DbContext снова запускаю команду -Force , она перезаписывает мой файл DbContext

Я использую мультитенант, и у меня есть пользовательский код внутри файла DbContext (новый конструктор, ошибка подключения в методе OnConfiguring)

как я могу обновить свои модели, не перезаписывая файл DbContext?

     public partial class MyContext : DbContext
    {
        private readonly ITenantDatabaseProvider _tenantProvider;

        public MyContext()
        {
        }

        public MyContext(DbContextOptions<MyContext> options)
            : base(options)
        {
        }
        public MyContext(ITenantDatabaseProvider tenantProvider)
        {
            _tenantProvider = tenantProvider;
        }
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                optionsBuilder.UseSqlServer(_tenantProvider.GetTenantConnectionString().Result);
                //.AddInterceptors(new HintCommandInterceptor());
            }

            base.OnConfiguring(optionsBuilder);
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
        }
        partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
        
    }
 

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

1. Для этого сценария вы должны поместить свою конфигурацию за пределы созданного вами DbContext. Он объявлен как частичный класс, поэтому поместите свои пользовательские данные в отдельный частичный класс.

Ответ №1:

Хотя в другом ответе указано использовать другой конструктор, он не объясняет, как и почему.

Гораздо проще отделить контекст БД от концепции арендаторов, единственное, что вам нужно от вашего арендатора, это строка подключения? Ну, вы можете передать его через параметры.

 public MyContext(DbContextOptions<MyContext> options)
    : base(options)
{
}
 

Чтобы сохранить ту же логику, используйте динамическое построение параметров для каждого экземпляра контекста БД

 services.AddDbContext<ApplicationCoreDbContext>((services, builder) =>
{
    var tenantProvider = services.GetRequiredService<ITenantDatabaseProvider>();
    builder.UseSqlServer(tenantProvider.GetTenantConnectionString().Result);
});
 

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

1. как я могу передать строку подключения через параметры? файл MyContext.cs будет сгенерирован снова и удалит мои изменения при Scaffold-DbContext последующем запуске

2. builder.UseSqlServer в моем фрагменте передается строка подключения через параметры. контейнер внедрения зависимостей использует конструктор параметров для создания нового экземпляра контекста БД

3. таким образом, вам вообще не нужно public MyContext(ITenantDatabaseProvider tenantProvider)

4. services.AddDbContext... это в файле запуска, мне нужно менять соединение с каждым запросом, я получаю клиента (идентификатор приложения) из заголовков http

5. с ограниченным жизненным циклом этот код в файле запуска будет выполняться для каждого запроса. на самом деле выполняется не AddDbContext выполнение, а лямбда-выражение внутри, которое создает параметры