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 小时前
每天认识一个组件:数据治理Apache Atlas
大数据
数字新视界2 小时前
2026模块化机房选型指南:行业市场发展趋势、占有率与竞争梯队分析报告解析
大数据·人工智能·物联网·数据中心·微模块机房·模块化机房·冷通道
姜穆澜4 小时前
OneID 从 0 到 1 完整生产案例(四)
大数据
OsDepK4 小时前
项目快速Git至仓库(完整版)
大数据·git·elasticsearch·搜索引擎
合米AI SOP系统5 小时前
传统产线如何快速上马落地 AI 防错?合米科技 AI SOP 7天即可上线。
大数据·人工智能·科技
思录Echo5 小时前
什么决定具身智能的最终走向?多技术路线与落地现实辨析
大数据·人工智能
xiaohaiAIgeo5 小时前
【2026年】AI监控加行为分析守护实验室安全
大数据·人工智能·科普知识
林墨聊AIGC6 小时前
动漫AI视频创作工具在哪找到的?2026年最新动漫AI视频平台与软件指南
大数据·人工智能·ai作画·aigc·音视频
故七月7 小时前
告别 AI 时代品牌 “隐身”:万域智瞰 AI‑GEO,构建品牌大模型时代营销新基建
大数据·人工智能
数字孪生视频孪生8 小时前
三维实时重构异构底座 核工危化无感定位跨境轨迹一屏统揽
大数据·运维·人工智能·重构·架构