1

介绍。我发现了一个问题和一个与该问题相关的问题:

elastic-db-tools github 问题。2015

堆栈溢出问题。2015

实际上,我使用多租户架构。使用最新.net core的 ,ef coreElasticScale. 大多数时候我只和一个租户一起工作——通常情况下。ShardMapManager提供SqlConnection,然后我可以DbContext使用它进行创建。

另外我有以下情况 - 我需要一次请求多个分片。像 - 通过所有租户寻找客户。

ElasticScale为此MultiShardConnection。我必须编写通常的 ADO.NET 查询来解决这个问题。我不喜欢真正的 ADO.NET 查询。整个解决方案适用于 ORM - EF,因此我想在任何地方使用 ORM!我试图找到类似 EF 适配器的东西......

好的。我写了以下解决方案:

public sealed class TenantDataContextFactory : ITenantDataContextFactory
{
    private readonly Lazy<string> _cachedConnectionString;

    private readonly IShardingService _shardingService;
    private readonly IConfigurationManager _configurationManager;
    private readonly ILogger<TenantDataContextFactory> _logger;

    //sp_set_session_context required MSSQL SERVER 2016 or above!!!
    private const string SpSetSessionContextQuery = @"exec sp_set_session_context @key=N'TenantId', @value=@TenantId";

    public async Task<TenantDataContext> CreateAsync(Guid tenantId)
    {
        SqlConnection sqlConnection = null;
        try
        {
            sqlConnection = await _shardingService.ShardMap
                .OpenConnectionForKeyAsync(key: tenantId,
                                           connectionString: _cachedConnectionString.Value,
                                           options: ConnectionOptions.Validate)
                .ConfigureAwait(false);

            var cmd = sqlConnection.CreateCommand();

            cmd.CommandText = SpSetSessionContextQuery;
            cmd.Parameters.AddWithValue("@TenantId", tenantId);

            await cmd.ExecuteNonQueryAsync().ConfigureAwait(false);

            return new TenantDataContext(tenantId, sqlConnection);
        }
        catch (Exception ex)
        {
            sqlConnection?.Dispose();

            _logger.LogCritical(ex, $"Create(). Create {nameof(TenantDataContext)} for {tenantId} was ended with an error!");
            throw;
        }
    }
}

public class MultiTenantConnectionFactory : IMultiTenantConnectionFactory
{
    private readonly IShardingService _shardingService;
    private readonly ITenantDataContextFactory _tenantDataContextFactory;

    public async Task<IReadOnlyCollection<TenantDataContext>> GetContexts()
    {
        var shards = _shardingService.RegisteredTenants;
        var connectionsTasks = shards.Select(x => _tenantDataContextFactory.CreateAsync(x));

        return await Task.WhenAll(connectionsTasks).ConfigureAwait(false);
    }
}


public sealed class MultiTenantRepository<T> : IMultiTenantRepository<T> where T : class, ITenantEntity
{
    private readonly IMultiTenantConnectionFactory _multiTenantConnectionFactory;

    public async Task<IList<T>> Find(Expression<Func<T, bool>> filter)
    {
        var dataContexts = await _multiTenantConnectionFactory.GetContexts().ConfigureAwait(false);

        var tasksList = dataContexts.Select(async x =>
        {
            await using (x)
            {
                return await x.Set<T>().Where(filter).ToListAsync().ConfigureAwait(false);
            }
        });

        var results = await Task.WhenAll(tasksList).ConfigureAwait(false);

        return results.SelectMany(x => x).ToList();
    }
}

但我不喜欢这个解决方案!管理连接,等待很多任务......我认为这个解决方案很慢......谁能解释我应该如何使用MultiShardConnection没有 ADO.NET?!

我想测试我的解决方案和 ADO.NET 查询性能。如果找不到其他解决方案或使用 ADO.NET,我想我将不得不放弃。

PS我知道ValueTaskTask<T>我很快就会改变习惯ValueTask

4

0 回答 0