ADOMD.NET连接状态轮询异常及Analysis Service持久连接实现咨询
问题产生原因
AdomdConnection的State属性属于客户端本地缓存的状态标识,仅在客户端主动调用Open()、Close()、Dispose()等方法时才会更新,不会主动和Analysis Service服务端做实时心跳校验。当服务端主动关闭、网络中断等场景发生时,客户端无法主动感知到连接异常,所以会一直返回Open的错误状态。
准确获取真实连接状态的方法
仅依赖State属性无法判断连接有效性,必须通过向服务端发送轻量探测请求的方式校验连接是否正常:
- 选择无业务开销的探测语句,比如
SELECT 1或者查询系统视图SELECT TOP 1 * FROM $SYSTEM.DISCOVER_PROPERTIES - 探测请求执行成功则连接有效,抛出连接相关异常则证明连接已断开
持久连接+自动重连实现方案
你可以参考以下实现逻辑,满足每3秒执行查询、异常自动重连的需求:
using Microsoft.AnalysisServices.AdomdClient; using System; public class SsasPersistentConnection { private string _connectionString; private AdomdConnection _connection; // 探测用的轻量SQL private const string DetectSql = "SELECT 1"; // 重连最大重试次数 private const int MaxRetryCount = 5; // 重连间隔(毫秒) private const int RetryInterval = 1000; public SsasPersistentConnection(string connectionString) { _connectionString = connectionString; } // 连接初始化/重连方法 private bool TryConnect() { // 先释放旧连接资源 _connection?.Dispose(); _connection = null; for (int i = 0; i < MaxRetryCount; i++) { try { _connection = new AdomdConnection(_connectionString); _connection.Open(); // 刚打开的连接也做一次探测,避免拿到无效连接 using var detectCmd = new AdomdCommand(DetectSql, _connection); detectCmd.ExecuteScalar(); return true; } catch (Exception ex) { Console.WriteLine($"连接失败,第{i+1}次重试,错误:{ex.Message}"); _connection?.Dispose(); _connection = null; System.Threading.Thread.Sleep(RetryInterval); } } return false; } // 执行查询的公共方法 public object ExecuteQuery(string sql) { // 先校验连接有效性 if (_connection == null || _connection.State != System.Data.ConnectionState.Open) { if (!TryConnect()) { throw new Exception("SSAS连接重试多次仍失败"); } } try { using var cmd = new AdomdCommand(sql, _connection); return cmd.ExecuteScalar(); // 如果是查询结果集可以用ExecuteReader,按业务需求调整 } catch (AdomdConnectionException) { // 捕获连接类异常,触发重连后再重试一次查询 if (TryConnect()) { using var cmd = new AdomdCommand(sql, _connection); return cmd.ExecuteScalar(); } throw; } catch (Exception) { // 其他业务异常自行处理 throw; } } // 定时任务入口 public void StartTimerTask(string businessSql, int intervalSeconds = 3) { while (true) { try { var result = ExecuteQuery(businessSql); Console.WriteLine($"查询执行成功,结果:{result},时间:{DateTime.Now:yyyy-MM-dd HH:mm:ss}"); } catch (Exception ex) { Console.WriteLine($"查询执行失败,错误:{ex.Message},时间:{DateTime.Now:yyyy-MM-dd HH:mm:ss}"); } finally { System.Threading.Thread.Sleep(intervalSeconds * 1000); } } } } // 调用示例 class Program { static void Main(string[] args) { var connStr = "你的SSAS连接字符串"; var ssasClient = new SsasPersistentConnection(connStr); // 替换为你实际要执行的业务查询语句 var businessSql = "替换为你的业务查询SQL"; ssasClient.StartTimerTask(businessSql, 3); } }
内容的提问来源于stack exchange,提问作者Kaja
相关产品推荐
相关产品推荐

