do tnet Core - Entity Framework - несколько DbContexts выбирают неправильно DbContext - PullRequest
0 голосов
/ 29 января 2020

У меня есть две базы данных. При первом запуске решение проверит базы данных, а затем создаст их с помощью миграции. Миграции для обеих БД существуют, однако, при вызове для создания контекста при запуске он фактически обращается к неправильному сервису, и я не знаю почему.

Вот код, который, помимо прочего, создает контекст.

public static class StartupCATALOGExtension
{
    public static void EnsureCATALOGMigrationAndInitialise(this IApplicationBuilder app)
    {
        if (app == null) throw new ArgumentNullException(nameof(app));

        using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
        {
            var context = serviceScope.ServiceProvider.GetService<CATALOGContext>();
            var cryptoService = serviceScope.ServiceProvider.GetService<ICryptoService>();

            context.Database.Migrate();
            serviceScope.ServiceProvider.GetService<ICATALOGCounterInitialiser>()
                .InitialiseCATALOGCounters(context);
            serviceScope.ServiceProvider.GetService<ICATALOGStateInitialiser>().CATALOGInitialiseStates(context);
            serviceScope.ServiceProvider.GetService<ICATALOGSuburbInitialiser>().CATALOGInitialiseSuburbs(context);
            serviceScope.ServiceProvider.GetService<IRoleInitialiser>().InitialiseRoles(context);
            serviceScope.ServiceProvider.GetService<ITenantAndUserInitialisations>()
                .InitialiseTenantsAndUsers(context, cryptoService);
        }
    }
}

}

Я могу перейти к следующей строке:

var context = serviceScope.ServiceProvider.GetService<CATALOGContext>();

В этот момент он переходит к файлу Startup.cs и, в частности, к службам. раздел. У меня есть это там:

        services
            // Add framework services.
            .AddOptions()

            .AddDbContext<CATALOGContext>(options => options
                .UseSqlServer(Configuration
                    .GetConnectionString("CatalogConnection"), b => b.MigrationsAssembly("JobsLedger.CATALOG")))

            .AddDbContext<DATAContext>(options => options
                .UseSqlServer(Configuration
                    .GetConnectionString("TenantDbConnection"), a => a.MigrationsAssembly("JobsLedger.DATA")))

Предполагается, что go определенно:

            .AddDbContext<CATALOGContext>(options => options
                .UseSqlServer(Configuration
                    .GetConnectionString("CatalogConnection"), b => b.MigrationsAssembly("JobsLedger.CATALOG")))

Однако по какой-то причине я не могу понять, что он идет на другую службу ...

            .AddDbContext<DATAContext>(options => options
                .UseSqlServer(Configuration
                    .GetConnectionString("TenantDbConnection"), a => a.MigrationsAssembly("JobsLedger.DATA")))

Я понятия не имею, почему он перепрыгнул бы прямо через службу, предположительно, к go и, в конце концов, завершил бы службу другой базы данных.

Почему идет вторая обслуживание и, что более важно, как вы делаете это go для правильного обслуживания?

ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ

Для полноты вот строки подключения в моем файле appsettings:

"ConnectionStrings": {
    "CatalogConnection": "Server=(localdb)\\mssqllocaldb;Database=catalogDb;Trusted_Connection=True;MultipleActiveResultSets=true",
    "TenantDbConnection": "Server=(localdb)\\mssqllocaldb;Database=masterDb;Trusted_Connection=True;MultipleActiveResultSets=true"
},

и вот файл миграции:

using JobsLedger.AUTHORISATION.API.SessionMiddleware;
using JobsLedger.CATALOG;
using JobsLedger.DATA;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;
using System.IO;

namespace JobsLedger.API {
    public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<CATALOGContext> {
        public CATALOGContext CreateDbContext(string[] args) {
            IConfigurationRoot configuration = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json")
                .Build();

            var builder = new DbContextOptionsBuilder<CATALOGContext>();

            var userSession = new UserSession {
                ConnectionString = configuration.GetConnectionString("CatalogConnection")
            };

            builder.UseSqlServer(userSession.ConnectionString);

            return new CATALOGContext(builder.Options, userSession);
        }
    }
}
public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<DATAContext> {
    public DATAContext CreateDbContext(string[] args) {
        IConfigurationRoot configuration = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json")
            .Build();

        var builder = new DbContextOptionsBuilder<DATAContext>();

        var userSession = new UserSession {
            ConnectionString = configuration.GetConnectionString("TenantDbConnection")
        };
        return new DATAContext(builder.Options, userSession);
    }
}

1 Ответ

0 голосов
/ 30 января 2020

Что ж, с огромным интересом к этому вопросу, сегодня вечером я провел небольшое исследование.

Я загрузил реальную ошибку - по крайней мере, последнюю часть, и нашел ЭТО пост-ответ Роуэн Миллер.

По сути, мне нужно было использовать универсальный тип опций c. Итак, я изменил свой конструктор в каждом DbContext, чтобы отразить, что это на самом деле ..

Для моего CATALOGContext я изменил это:

public CATALOGContext(DbContextOptions options, IUserSession userSession) : base(options)
        {
            _userSession = userSession;
        }

На это:

public CATALOGContext(DbContextOptions<CATALOGContext> options, IUserSession userSession) : base(options)
        {
            _userSession = userSession;
        }

.. и теперь он выбирает правильный контекст для использования.

...