TDengine在NetCore中数据查询的使用

1、封装为帮助类的方式调用

仅需在配置类中增加TDengine节点的连接信息:http://localhost:6041

cs 复制代码
using System.Configuration;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace Utils
{
    public class TDengineDataHelper
    {
        private static readonly Lazy<TDengineDataHelper> _instance = new Lazy<TDengineDataHelper>(() => new TDengineDataHelper());
        private HttpClient _httpClient = null;
        private readonly string _authToken;
        private static readonly string _baseUrl = ConfigurationManager.AppSettings["TDengine"] ?? throw new InvalidOperationException("TDengine is not configured.");
        public TDengineDataHelper()
        {
            _httpClient= new HttpClient();

            // Basic Authentication
            var authString = Convert.ToBase64String(Encoding.UTF8.GetBytes($"root:taosdata"));
            _authToken = $"Basic {authString}";
            _httpClient.Timeout = TimeSpan.FromSeconds(30);
        }

        // 单例实例访问点
        public static TDengineDataHelper Instance => _instance.Value;

        /// <summary>
        /// TDengien数据查询
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="db"></param>
        /// <returns></returns>
        public async Task<TDengineResponse<T>> ExecuteQueryAsync<T>(string sql, string? db = null)
        {
            try
            {
                var requestUrl = $"{_baseUrl}/rest/sql";
                if (!string.IsNullOrEmpty(db))
                {
                    requestUrl += $"/{db}";
                }
                // 添加 row_with_meta 参数
                var queryParams = new Dictionary<string, string>();
                queryParams.Add("row_with_meta", "true");
                if (queryParams.Count>0)
                {
                    requestUrl += "?" + string.Join("&", queryParams.Select(kvp => $"{kvp.Key}={kvp.Value}"));
                }
                var request = new HttpRequestMessage(HttpMethod.Post, requestUrl);
                request.Headers.Add("Authorization", _authToken);
                request.Content = new StringContent(sql, Encoding.UTF8, "application/json");

                var response = await _httpClient.SendAsync(request);
                response.EnsureSuccessStatusCode();

                var result = await response.Content.ReadAsStringAsync();
                // 解析原始响应
                var responseResult = JsonSerializer.Deserialize<TDengineResponse<T>>(result);

                if (responseResult?.Code != 0)
                {
                    return null;
                }
                else
                {
                    return responseResult;
                }
            }
            catch (Exception ex)
            {
                Logger.Error(ex.Message);
                return null;
            }
        }
        
        
        // 释放资源
        public void Dispose()
        {
            _httpClient?.Dispose();
        }
        /// <summary>
        /// 格式化返回结果
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tdengineJsonResponse"></param>
        /// <returns></returns>
        public static List<T> GetFormateData<T>(string tdengineJsonResponse)
        {
            // 解析原始响应
            var response = JsonSerializer.Deserialize<TDengineResponse<T>>(tdengineJsonResponse);

            if (response?.Code != 0)
            {
                return new List<T>();
            }
            else
            {
                return response.Data;
            }

        }

        // 内部类用于解析TDengine响应
        public class TDengineResponse<T>
        {
            [JsonPropertyName("code")]
            public int Code { get; set; }

            [JsonPropertyName("column_meta")]
            public List<List<object>> ColumnMeta { get; set; }

            [JsonPropertyName("data")]
            public List<T> Data { get; set; }

            [JsonPropertyName("rows")]
            public int Rows { get; set; }
        }

    }
}

2、使用依赖注入的方式调用

(1)创建服务注册扩展类,实现对服务webSocket连接信息的注入

cs 复制代码
public static class TDengineServiceExtensions
{
    public static IServiceCollection AddTDengine(
        this IServiceCollection services,
        IConfiguration configuration,
        Action<TDengineOptions> configureOptions = null)
    {
        // 绑定配置
        var options = new TDengineOptions();
        configuration.GetSection("TDengine").Bind(options);

        // 允许外部配置覆盖
        configureOptions?.Invoke(options);

        // 注册选项
        services.AddSingleton(Options.Create(options));

        // 注册 HttpClient(使用命名客户端)
        services.AddHttpClient("TDengineClient", client =>
        {
            client.BaseAddress = new Uri(options.ConnectionUrl);
            client.Timeout = TimeSpan.FromSeconds(options.TimeoutSeconds);

            var authString = Convert.ToBase64String(
                Encoding.UTF8.GetBytes($"{options.Username}:{options.Password}"));
            client.DefaultRequestHeaders.Authorization =
                new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", authString);
            client.DefaultRequestHeaders.Accept.Add(
                new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
        });

        // 注册主服务
        services.AddScoped<ITDengineService, TDengineDataService>();

        return services;
    }

}
public class TDengineOptions
{
    public string ConnectionUrl { get; set; } = "http://localhost:6041";
    public string Username { get; set; } = "root";
    public string Password { get; set; } = "taosdata";
    public int TimeoutSeconds { get; set; } = 10;
}

(2)数据返回实体

cs 复制代码
public class TDengineResponse<T>
{
    [JsonPropertyName("code")]
    public int Code { get; set; }

    [JsonPropertyName("column_meta")]
    public List<List<object>> ColumnMeta { get; set; }

    [JsonPropertyName("data")]
    public List<T> Data { get; set; }

    [JsonPropertyName("rows")]
    public int Rows { get; set; }
}

(3)服务接口类

cs 复制代码
 public interface ITDengineService
 {
     Task<TDengineResponse<T>> ExecuteQueryAsync<T>(string sql, string? db = null);
     void Dispose();
 }

(4)服务实现类

cs 复制代码
 public class TDengineDataService : ITDengineService, IDisposable
 {
     private readonly HttpClient _httpClient;
     private readonly TDengineOptions _options;
     private readonly ILogger<TDengineDataService> _logger;

     public TDengineDataService(IHttpClientFactory httpClientFactory, IOptions<TDengineOptions> options,ILogger<TDengineDataService> logger)
     {
         _logger = logger;
         _options = options.Value;

         // 从工厂获取命名客户端
         _httpClient = httpClientFactory.CreateClient("TDengineClient");
     }

     public void Dispose()
     {
         _httpClient?.Dispose();
     }

     public async Task<TDengineResponse<T>> ExecuteQueryAsync<T>(string sql, string? db = null)
     {
         try
         {
             var endpoint = string.IsNullOrEmpty(db) ? "rest/sql" : $"rest/sql/{db}";
             var requestUrl = $"{endpoint}?row_with_meta=true";

             var request = new HttpRequestMessage(HttpMethod.Post, requestUrl);
             request.Content = new StringContent(sql, Encoding.UTF8, "application/json");

             var response = await _httpClient.SendAsync(request);
             response.EnsureSuccessStatusCode();

             var result = await response.Content.ReadAsStringAsync();
             var responseResult = JsonSerializer.Deserialize<TDengineResponse<T>>(result);

             if (responseResult?.Code != 0)
             {
                 _logger.LogWarning("TDengine query failed with code: {Code}", responseResult?.Code);
                 return null;
             }

             return responseResult;
         }
         catch (Exception ex)
         {
             _logger.LogError(ex, "TDengine query error");
             return null;
         }
     }
 }
相关推荐
人道领域1 分钟前
AI抢人大战:谁在收割你的红包
大数据·人工智能·算法
qq_124987075323 分钟前
基于Hadoop的信贷风险评估的数据可视化分析与预测系统的设计与实现(源码+论文+部署+安装)
大数据·人工智能·hadoop·分布式·信息可视化·毕业设计·计算机毕业设计
Hello.Reader28 分钟前
Flink 使用 Amazon S3 读写、Checkpoint、插件选择与性能优化
大数据·flink
零售ERP菜鸟1 小时前
范式革命:从“信息化”到“数字化”的本质跃迁
大数据·人工智能·职场和发展·创业创新·学习方法·业界资讯
Hello.Reader1 小时前
Flink 对接 Google Cloud Storage(GCS)读写、Checkpoint、插件安装与生产配置指南
大数据·flink
浪子小院2 小时前
ModelEngine 智能体全流程开发实战:从 0 到 1 搭建多协作办公助手
大数据·人工智能
AEIC学术交流中心3 小时前
【快速EI检索 | ACM出版】2026年大数据与智能制造国际学术会议(BDIM 2026)
大数据·制造
wending-Y3 小时前
记录一次排查Flink一直重启的问题
大数据·flink
UI设计兰亭妙微3 小时前
医疗大数据平台电子病例界面设计
大数据·界面设计
初恋叫萱萱4 小时前
模型瘦身实战:用 `cann-model-compression-toolkit` 实现高效 INT8 量化
大数据