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;
}
}
}