【问题标题】:Testing an Entity Framework database connection测试实体框架数据库连接
【发布时间】:2013-10-13 05:08:46
【问题描述】:

我有一个通过实体框架连接到 MYSQL 数据库的应用程序。它可以 100% 完美运行,但我想添加一小段代码,用于在应用启动时测试与数据库的连接。

我的想法是简单地对数据库运行一个小命令并捕获任何异常,但是如果出现问题(例如 App.Config 丢失或数据库服务器关闭),应用程序需要大量时间来运行此代码然后抛出异常(〜1分钟)。我想这是由于连接超时等原因,但我对这些属性进行了摆弄,但无济于事。

有人能提供关于去哪里的任何想法吗?

【问题讨论】:

标签: c# mysql entity-framework testing database-connection


【解决方案1】:

我知道这是一个老问题,但对于任何寻求更新实现的人来说,这是我的答案。

我可以使用CanConnect 来检查数据库的状态:

_database.Database.CanConnect();

# Async too
await _database.Database.CanConnectAsync(_cancellationTokenSource.Token);

我希望这对其他人也有帮助。干杯!

【讨论】:

    【解决方案2】:

    在 EntityFramework Core 中,您可以简单地调用:Database.CanConnect();

    (使用 EF Core 2.2.1)

    摘要:确定数据库是否可用以及是否可以连接。

    请注意,能够连接到数据库并不意味着它在架构创建等方面是最新的。

    【讨论】:

    • 还要注意CanConnect在数据库服务器离线时不会返回false,它会抛出异常
    【解决方案3】:

    我正在使用以下代码进行 MS SQL 连接。也许,它对 MySQL 也很有用。您甚至不需要使用 EF 或 EF Core。

        public bool IsDbConnectionOK()
        {
            SqlConnectionStringBuilder conStr = new SqlConnectionStringBuilder
            {
                DataSource = ButtonServerName.Text,  // <-- My Form Elements
                InitialCatalog = ButtonDBName.Text, // <-- My Form Elements
                UserID = EditUserName.Text, // <-- My Form Elements
                Password = EditPassword.Text, // <-- My Form Elements
                IntegratedSecurity = false,
                ConnectTimeout = 30
            };
    
            string connectionstring = conStr.ToString();
    
            try
            {
                using (System.Data.SqlClient.SqlConnection connection = new System.Data.SqlClient.SqlConnection(connectionstring))
                {
                    connection.Open();
                    return true;
                }
            }
            catch (System.Data.SqlClient.SqlException ex)
            {
                MessageBox.Show(ex.Message + Environment.NewLine +
                    "Error line: " + ex.LineNumber + Environment.NewLine +
                    "Procedure name: " + ex.Procedure);
                return false;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return false;
            }
        }
    

    【讨论】:

      【解决方案4】:

      您只是想查看数据库连接是否有效?如果是这样,请查看

      using (DatabaseContext dbContext = new DatabaseContext())
      {
           dbContext.Database.Exists();
      }
      

      http://msdn.microsoft.com/en-us/library/gg696617(v=vs.103).aspx

      为了检查服务器机器是否启动,数据库服务器或网络服务服务器,试试这个:

      public PingReply Send( string hostNameOrAddress )

      http://msdn.microsoft.com/en-us/library/7hzczzed.aspx

      【讨论】:

      • 我通过在 SQL Server 中使用 db 'offline' 对此进行了测试,并且 Database.Exists() 仍然返回 true。需要注意的事情...
      • 最好的方法是使用mysql dll连接器并手动完成。如果您使用迁移,它将返回 false,但连接正常!
      • 这不适用于 MS SQL,Exists 返回 true 并且 DBSet.Load 同时给出异常。
      • 什么是例外?
      • '我相信上述解决方案适用于早于 EF6 的 EF 版本' 事实上,发布答案时,EF6 并不存在。感谢您发布详细信息,如果需要,我将查看并更新答案。
      【解决方案5】:

      @Danilo Breda 指出的解决方案是调用 DbContext.Database.Connection.Open()

      已用 EF6 测试。

      我的实现:

          public static bool CheckConnection()
          {
              try
              {
                  MyContext.Database.Connection.Open();
                  MyContext.Database.Connection.Close();
              }
              catch(SqlException)
              {
                  return false;
              }
              return true;
          }
      

      【讨论】:

      • 我最喜欢这个解决方案,是的,你不应该对流逻辑使用异常(通常是;-))
      • 我会将其添加到单元测试中。
      • 我知道,如果我想确保 MySQL 服务器在每次与数据库交互时都启动,我需要为每个操作执行if (CheckConnection()) {..}(为了避免应用程序错误,以防万一MySQL 服务器已关闭)。知道如何在全球范围内实施此检查吗?所以就没有必要打电话再打电话CheckConnection() 了?
      • @W.M.最好的选择是实现连接弹性,请参阅以下文章。 codeproject.com/Tips/758469/…
      【解决方案6】:

      我将此代码用于我的项目:

      private bool TestConnectionEF()
              {
                  using (var db = new SistemaContext())
                  {
                      try
                      {
                          db.Database.Connection.Open();
                          if (db.Database.Connection.State == ConnectionState.Open)
                          {
                              Console.WriteLine(@"INFO: ConnectionString: " + db.Database.Connection.ConnectionString 
                                  + "\n DataBase: " + db.Database.Connection.Database 
                                  + "\n DataSource: " + db.Database.Connection.DataSource 
                                  + "\n ServerVersion: " + db.Database.Connection.ServerVersion 
                                  + "\n TimeOut: " + db.Database.Connection.ConnectionTimeout);
                              db.Database.Connection.Close();
                              return true;
                          }
                          return false;
                      }
                      catch(Exception ex)
                      {
                          throw ex;
                      }
                  }
              }
      

      【讨论】:

      • 鉴于您使用 using 块,connection.close() 是否必要?
      • @ComeIn 如果您的 Context 类在 dispose 方法上有一个 databaseconnectionclose,您可以将其关闭。我不知道 ORM 是否这样做。对我来说,当我打开连接时,我需要关闭它。如果我不打开,我不需要关闭。
      • EF 将关闭底层 DBContext。除非必要,否则最好不要手动执行此操作。见:stackoverflow.com/questions/28067150/…
      • @ComeIn EF 如果为我打开它将关闭,在我的代码上我手动打开它,所以我需要关闭它(“如果您手动打开连接,EF 不会在数据库操作完成。”)
      • 然后我想我们回到我原来的问题。您是否真的需要明确调用 Connection.Open() ,如果不需要,则删除该调用。这是推荐的用法,但当然,如果您想要手动管理数据库连接的额外麻烦,请照常进行。
      【解决方案7】:

      我使用了来自@Sandor 的答案并做了一个extension method 与EntityFramework Core 一起使用。

      代码如下:

      using Microsoft.EntityFrameworkCore;
      using System.Data.Common;
      
      namespace TerminalInventory
      {
          public static class ExtensionMethods
          {
              public static bool TestConnection(this DbContext context)
              {
                  DbConnection conn = context.Database.GetDbConnection();
      
                  try
                  {
                      conn.Open();   // Check the database connection
      
                      return true;
                  }
                  catch
                  {
                      return false;
                  }
              }
          }
      }
      

      现在您只需调用:

      if (!context.TestConnection())
      {
          logger.LogInformation("No database connection. Check the connection string in settings.json. {0}", configuration["connectionString"]);
      
          return;
      }
      

      【讨论】:

      • 既然你不在 using 块内,你不应该在调用 open() 后关闭连接以避免不必要的leaving the connection open吗?
      • 是否需要关闭连接?还是可以让它保持打开状态?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多