Как использовать сегментирование базы данных с EF Core и C# " - PullRequest
10 голосов
/ 06 мая 2020

В настоящее время я конвертирую свое 6-летнее приложение C# в. NET Core v3 и EF Core (а также использую Blazor). Большая часть его работает, за исключением части Sharding.
Наше приложение создает новую базу данных для каждого клиента. Мы используем для этого более или менее этот код: https://docs.microsoft.com/en-us/azure/sql-database/sql-database-elastic-scale-use-entity-framework-applications-visual-studio
Сейчас я пытаюсь преобразовать его в EF Core, но застрял в этой части:

        // C'tor to deploy schema and migrations to a new shard
        protected internal TenantContext(string connectionString)
            : base(SetInitializerForConnection(connectionString))
        {
        }

        // Only static methods are allowed in calls into base class c'tors
        private static string SetInitializerForConnection(string connnectionString)
        {
            // We want existence checks so that the schema can get deployed
            Database.SetInitializer<TenantContext<T>>(new CreateDatabaseIfNotExists<TenantContext<T>>());
            return connnectionString;
        }

        // C'tor for data dependent routing. This call will open a validated connection routed to the proper
        // shard by the shard map manager. Note that the base class c'tor call will fail for an open connection
        // if migrations need to be done and SQL credentials are used. This is the reason for the 
        // separation of c'tors into the DDR case (this c'tor) and the internal c'tor for new shards.
        public TenantContext(ShardMap shardMap, T shardingKey, string connectionStr)
            : base(CreateDDRConnection(shardMap, shardingKey, connectionStr), true /* contextOwnsConnection */)
        {
        }

        // Only static methods are allowed in calls into base class c'tors
        private static DbConnection CreateDDRConnection(ShardMap shardMap, T shardingKey, string connectionStr)
        {
            // No initialization
            Database.SetInitializer<TenantContext<T>>(null);

            // Ask shard map to broker a validated connection for the given key
            var conn = shardMap.OpenConnectionForKey<T>(shardingKey, connectionStr, ConnectionOptions.Validate);
            return conn;
        }

Приведенный выше код не компилируется, потому что объект Database таким образом не существует в EF Core. Я предполагаю, что могу упростить его, используя TenantContext.Database.EnsureCreated(); где-нибудь. Но я не могу понять, как изменить методы, какие удалить, какие изменить (и как).

Конечно, я искал пример с использованием сегментирования и EF Core, но не смог ' не найду. Кто-нибудь здесь делал это раньше в EF Core и хочет поделиться?

Я специально ищу, что вставить startup.cs и как создать новый сегмент / базу данных при создании нового клиента .

1 Ответ

5 голосов
/ 06 мая 2020

В EF.Core просто разрешите осколок в OnConfiguring. EG

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    var con = GetTenantConnection(this.tenantName);

    optionsBuilder.UseSqlServer(con,o => o.UseRelationalNulls());

    base.OnConfiguring(optionsBuilder);
}

Обратите внимание, что если у вас есть служба или фабрика, которая возвращает open DbConnections, вам нужно закрыть () / Dispose () их в DbContext.Dispose ( ). Если вы получили строку подключения или закрытое соединение, то DbContext позаботится о его закрытии. DbContext. Но картина та же. Просто сохраните внедренный экземпляр службы в поле DbContext и используйте его в OnConfiguring.

...