【问题标题】:SQL Azure Transient Fault with Data Access Application Block 6.0带有数据访问应用程序块 6.0 的 SQL Azure 瞬态故障
【发布时间】:2014-06-04 18:20:01
【问题描述】:

在我们的一个应用程序中,我们使用的是 Enterprise Library 6.0 数据访问块。我们将数据库对象初始化为

DatabaseFactory.SetDatabaseProviderFactory(new DatabaseProviderFactory());
Database database = DatabaseFactory.CreateDatabase();

我们需要为上述数据库对象设置 SqlAzureTransientErrorDetectionStrategy 和/或 RetryPolicy

是否有任何方法可以使用 Windows Azure SQL 的数据访问应用程序块和瞬态故障处理应用程序块来完成上述任务?

我知道我们可以使用 ReliableSqlConnection 实现它,但找不到数据访问应用程序块和瞬态故障处理应用程序块的任何资源。

【问题讨论】:

    标签: azure-sql-database enterprise-library


    【解决方案1】:

    更新开始

    我在这里添加完整的类实现,以便它对其他用户也有用。

    public class SqlAzureDatabase : SqlDatabase
    {
        public RetryPolicy _retryPolicy { get; set; }
    
        public SqlAzureDatabase(string connectionString, RetryPolicy retryPolicy)
            : base(connectionString)
        {
            this._retryPolicy = retryPolicy;
        }
    
        protected override DatabaseConnectionWrapper GetWrappedConnection()
        {
            return new DatabaseConnectionWrapper(GetNewOpenConnection());
        }
    
        private DbConnection GetNewOpenConnection()
        {
            SqlConnection connection = null;
            try
            {
                connection = base.CreateConnection() as SqlConnection;
                if (connection != null)
                {
                    connection.OpenWithRetry(this._retryPolicy);
                }
            }
            catch
            {
                if (connection != null && connection.State != System.Data.ConnectionState.Closed)
                    connection.Close();
    
                throw;
            }
    
            return connection;
        }
    
        public override int ExecuteNonQuery(DbCommand command)
        {
            using (DatabaseConnectionWrapper wrapper = GetOpenConnection())
            {
                PrepareCommand(command, wrapper.Connection);
                return DoExecuteNonQueryWithRetry(command);
            }
        }
    
        private int DoExecuteNonQueryWithRetry(DbCommand command)
        {
            if (command == null) throw new ArgumentNullException("command");
    
            SqlCommand sqlCommand = command as SqlCommand;
    
            if (sqlCommand != null)
            {
                int rowsAffected = sqlCommand.ExecuteNonQueryWithRetry(this._retryPolicy);
                return rowsAffected;
            }
    
            return 0;
        }
    
        public override IDataReader ExecuteReader(DbCommand command)
        {
            using (DatabaseConnectionWrapper wrapper = GetOpenConnection())
            {
                PrepareCommand(command, wrapper.Connection);
                IDataReader realReader = DoExecuteReaderWithRetry(command, CommandBehavior.Default);
                return CreateWrappedReader(wrapper, realReader);
            }
        }
    
        private IDataReader DoExecuteReaderWithRetry(DbCommand command, CommandBehavior cmdBehavior)
        {
            if (command == null) throw new ArgumentNullException("command");
    
            SqlCommand sqlCommand = command as SqlCommand;
    
            if (sqlCommand != null)
            {
                IDataReader reader = sqlCommand.ExecuteReaderWithRetry(_retryPolicy);
                return reader;
            }
    
            return null;
        }
    
        public override object ExecuteScalar(DbCommand command)
        {
            using (DatabaseConnectionWrapper wrapper = GetOpenConnection())
            {
                PrepareCommand(command, wrapper.Connection);
                return DoExecuteScalarWithRetry(command);
            }
        }
    
        private object DoExecuteScalarWithRetry(IDbCommand command)
        {
            if (command == null) throw new ArgumentNullException("command");
    
            SqlCommand sqlCommand = command as SqlCommand;
    
            if (sqlCommand != null)
            {
                object returnValue = sqlCommand.ExecuteScalarWithRetry(this._retryPolicy);
                return returnValue;
            }
    
            return null;
        } 
    }
    

    SqlAzureDatabase 类的作用如下所述。

    Database database = new SqlAzureDatabase(connectionString, retryPolicy);
    

    更新结束


    我有类似的需求,最终创建了SqlDatabase 类的扩展并将GetWrappedConnection 方法覆盖为:

    protected override DatabaseConnectionWrapper GetWrappedConnection()
    {
                return new DatabaseConnectionWrapper(GetNewOpenConnection());
    }
    

    GetNewOpenConnection() 是一个私有方法

    private DbConnection GetNewOpenConnection()
     {
                SqlConnection connection = null;
                try
                {
                    connection = CreateConnection() as SqlConnection;
                    if(connection != null)
                    {
                        connection.OpenWithRetry(this._retryPolicy);
                    }
    
                    //instrumentationProvider.FireConnectionOpenedEvent();
                }
                catch
                {
                    if (connection != null)
                        connection.Close();
    
                    throw;
                }
    
                return connection;
      }
    

    下载SqlAzureDatabase类@http://1drv.ms/SJft8o。它主要是为了支持联邦,但您可以修改它或只使用基本构造函数来处理注入重试策略

    public SqlAzureDatabase(string connectionString)
               : this(connectionString, FederationType.None, null, null, null)
    {
    }
    

    【讨论】:

    • 我认为瞬态错误也可能发生在执行命令时,而不仅仅是在打开连接时,因此您还需要覆盖常用方法,如 ExecuteReader、ExecuteScalar 等。
    • @NandipMakwana 课程代码的链接已损坏。你能把它作为一个要点发布到 github 上让它永远存在吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-05
    相关资源
    最近更新 更多