.net - 动态选择 Entity Framework 中事件可用数据库的连接字符串

标签 .net entity-framework model-view-controller connection-string

目前,我们使用两台具有相同数据库名称和设置的服务器。我想获取处于事件状态或我可以轻松连接到的连接字符串。举例来说,有时我们在 server-1 所在的地方停电,这样我就可以使用 server-2,因为它位于不同的地方。

这里,我在 .NET 中使用连接字符串帮助程序类,但没有 Entity Framework ,但我无法为 Entity Framework 实现它。

在 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 类对 Entity Framework 进行相同的设置。我应该能够从 Web 配置传递连接字符串的名称,并检查它是否有效并且应该重定向到它。

最佳答案

根据您的需求,我可以提出解决方案。我假设您已经为 EF 提供了默认连接字符串。

现在你可以这样做了。

第 1 步。为 EF DB Context 创建扩展方法:

公共(public)静态类ConnectionTools {

public static void CheckConnection(this DbContext source)
{

    if (!source.Database.Exists())
    {
        //TODO: logic to read all your connection string into a list
        string connectionStrings = new List<string>();
        foreach (var connection in connectionStrings)
        {
            //set new connection and check
            source.Database.Connection.ConnectionString = connection;
            if (source.Database.Exists())
            {
            //break loop
            }
        }
    }
}

}

第 2 步。在调用部分执行如下操作:

-

public void SomeOperation()
{
    //assuming you already have your context injected
    var employees = _context.CheckConnection().Employees.ToList();
}

关于.net - 动态选择 Entity Framework 中事件可用数据库的连接字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58748979/

相关文章:

model-view-controller - Ext JS 的 MVC 是反模式吗?

c# - ACRA 类似于 C# .NET 的崩溃报告库

.net - Windows UI 自动化无法识别按钮控件

.net - 使用 ftp Github Actions 发布和部署 dotnet

c# - 在 mysql 上使用带有参数的 Database.ExecuteSqlCommand 的正确语法是什么?

asp.net-mvc - MVC 使用派生类创建

.net - 不能 .loadby sos mscorwks 或 .loadby sos clr

.net - 我可以从数据库项目初始化数据库吗?

c# - 编写谓词以使用 Entity Framework 搜索存储库时出现问题(相当于在 SQL 中使用 Join)

java - 您将 Java 应用程序的核心放在哪里?