介绍。我发现了一个问题和一个与该问题相关的问题:
elastic-db-tools github 问题。2015
实际上,我使用多租户架构。使用最新.net core
的 ,ef core
和ElasticScale
. 大多数时候我只和一个租户一起工作——通常情况下。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我知道ValueTask
!Task<T>
我很快就会改变习惯ValueTask
。