В настоящее время мы используем два сервера с одинаковым именем базы данных и настройками. Я хотел бы взять строку подключения для той, которая активна, или той, к которой я могу легко подключиться. Скажем, например, иногда у нас отключение питания в том месте, где расположен сервер-1, поэтому я могу использовать сервер-2, так как он расположен в другом месте.
Здесь я использую помощник строки подключениякласс в .NET для одного без сущности, но я не могу добиться этого для сущности.
в web.config
<add name="dbAdo1a" connectionString="connection for Server-1" providerName="abc" />
<add name="dbAdo1b" connectionString="connection for Server-2" providerName="abc" />
в C #
public class ConnectionStringHelper
{
private static readonly Timer Timer;
private static readonly ConcurrentDictionary<int, string> BestConnectionStrings;
private const int LoopCount = 3;
static ConnectionStringHelper()
{
BestConnectionStrings = new ConcurrentDictionary<int, string>();
for (var i = 1; i <= LoopCount; i++)
{
GetQuickOneSync(i);
}
Timer = new Timer(Constants.ConnectionRefreshTimeout * 1000);
Timer.Elapsed += async (sender, e) => await HandleTimerElapsed(sender, e).ConfigureAwait(false);
Timer.AutoReset = false;
Timer.Start();
}
public static string GetConnectionString(int wareHouseId)
{
if (!BestConnectionStrings.ContainsKey(wareHouseId))
{
return string.Empty; // just swallow the error if no connection available
}
return BestConnectionStrings[wareHouseId];
}
private static async Task HandleTimerElapsed(object sender, ElapsedEventArgs e)
{
try
{
// Find the quickies for each of the connection strings
var sw = new Stopwatch();
sw.Start();
// TODO - three sets of ConnectionStrings for now, make dynamic
for (var i = 1; i <= LoopCount; i++)
{
await GetQuickOne(i).ConfigureAwait(false);
}
}
catch (Exception ex)
{
}
finally
{
Timer.Start();
}
async Task GetQuickOne(int wareHouseId)
{
var quickone = string.Empty;
var quickest = long.MaxValue;
var sw = new Stopwatch();
for (var c = 'a'; c <= 'z'; c++)
{
var cs = ConfigurationManager.ConnectionStrings[$"dbAdo{wareHouseId}{c}"]?.ConnectionString;
if (string.IsNullOrEmpty(cs)) break;
sw.Restart();
// open connection and see how long it takes
using (var connection = new SqlConnection(cs))
{
try
{
await connection.OpenAsync().ConfigureAwait(false);
}
catch (Exception exception)
{
continue; // move on
}
var milliseconds = sw.ElapsedMilliseconds;
if (milliseconds < quickest) // quickest so far?
{
quickest = milliseconds;
quickone = cs;
}
if (milliseconds <= Constants.ConnectionOkThreshold) // is ok if quickest under the threshold, go no further
{
break;
}
}
}
BestConnectionStrings[wareHouseId] = quickone;
}
}
private static void GetQuickOneSync(int wareHouseId)
{
var quickone = string.Empty;
var quickest = long.MaxValue;
var sw = new Stopwatch();
for (var c = 'a'; c <= 'z'; c++)
{
var cs = ConfigurationManager.ConnectionStrings[$"dbAdo{wareHouseId}{c}"]?.ConnectionString;
if (string.IsNullOrEmpty(cs)) break;
sw.Restart();
// open connection and see how long it takes
using (var connection = new SqlConnection(cs))
{
try
{
connection.Open();
}
catch (Exception exception)
{
continue; // move on
}
var milliseconds = sw.ElapsedMilliseconds;
if (milliseconds < quickest) // quickest so far?
{
quickest = milliseconds;
quickone = cs;
}
if (milliseconds <= Constants.ConnectionOkThreshold) // is ok if quickest under the threshold, go no further
{
break;
}
}
}
if (!string.IsNullOrEmpty(quickone))
BestConnectionStrings[wareHouseId] = quickone;
}
}
Я хотел бы сделать тот же вид настройки для структуры сущностей, используя класс System.Data.Entity.DbContext. Где я должен быть в состоянии передать имя строки подключения из веб-конфигурации и проверить, что она активно доступна, и она должна перенаправить на нее.