mirror of
https://gitee.com/dotnetchina/SqlSugar.git
synced 2025-08-23 22:11:36 +08:00
Add QuestDb rest api
This commit is contained in:
parent
6ef1afbb76
commit
e7be0ce07e
15
Src/Asp.NetCore2/SqlSugar.QuestDb.RestApi/HttpExtensions.cs
Normal file
15
Src/Asp.NetCore2/SqlSugar.QuestDb.RestApi/HttpExtensions.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace SqlSugar
|
||||||
|
{
|
||||||
|
public static class ISqlSugarClientExtensions
|
||||||
|
{
|
||||||
|
public static QuestDbRestAPI RestApi(this ISqlSugarClient db)
|
||||||
|
{
|
||||||
|
return new QuestDbRestAPI(db);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Web;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using CsvHelper;
|
||||||
|
|
||||||
|
namespace SqlSugar
|
||||||
|
{
|
||||||
|
internal class QuestDbRestAPHelper
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 逐行读取,包含空行
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="text"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static List<string> SplitByLine(string text)
|
||||||
|
{
|
||||||
|
List<string> lines = new List<string>();
|
||||||
|
byte[] array = Encoding.UTF8.GetBytes(text);
|
||||||
|
using (MemoryStream stream = new MemoryStream(array))
|
||||||
|
{
|
||||||
|
using (var sr = new StreamReader(stream))
|
||||||
|
{
|
||||||
|
string line = sr.ReadLine();
|
||||||
|
while (line != null)
|
||||||
|
{
|
||||||
|
lines.Add(line);
|
||||||
|
line = sr.ReadLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
166
Src/Asp.NetCore2/SqlSugar.QuestDb.RestApi/QuestDbRestAPI.cs
Normal file
166
Src/Asp.NetCore2/SqlSugar.QuestDb.RestApi/QuestDbRestAPI.cs
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
using CsvHelper;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Web;
|
||||||
|
|
||||||
|
namespace SqlSugar
|
||||||
|
{
|
||||||
|
|
||||||
|
public class QuestDbRestAPI
|
||||||
|
{
|
||||||
|
internal string url = string.Empty;
|
||||||
|
internal string authorization = string.Empty;
|
||||||
|
ISqlSugarClient db;
|
||||||
|
public QuestDbRestAPI(ISqlSugarClient db)
|
||||||
|
{
|
||||||
|
this.db = db;
|
||||||
|
string host = "";
|
||||||
|
string username = "";
|
||||||
|
string password = "";
|
||||||
|
|
||||||
|
url = host;
|
||||||
|
if (url.EndsWith("/"))
|
||||||
|
url = url.Remove(url.Length - 1);
|
||||||
|
|
||||||
|
if (!url.ToLower().StartsWith("http"))
|
||||||
|
url = $"http://{url}";
|
||||||
|
//生成TOKEN
|
||||||
|
if (!string.IsNullOrWhiteSpace(username) && !string.IsNullOrWhiteSpace(password))
|
||||||
|
{
|
||||||
|
var base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{username}:{password}"));
|
||||||
|
authorization = $"Basic {base64}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<string> ExecuteCommandAsync(string sql)
|
||||||
|
{
|
||||||
|
//HTTP GET 执行SQL
|
||||||
|
var result = string.Empty;
|
||||||
|
var client = new HttpClient();
|
||||||
|
var url = $"{this.url}/exec?query={HttpUtility.UrlEncode(sql)}";
|
||||||
|
if (!string.IsNullOrWhiteSpace(authorization))
|
||||||
|
client.DefaultRequestHeaders.Add("Authorization", authorization);
|
||||||
|
var httpResponseMessage = await client.GetAsync(url);
|
||||||
|
result = await httpResponseMessage.Content.ReadAsStringAsync();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ExecuteCommand(string sql)
|
||||||
|
{
|
||||||
|
return ExecuteCommandAsync(sql).GetAwaiter().GetResult();
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 批量快速插入
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="that"></param>
|
||||||
|
/// <param name="dateFormat">导入时,时间格式 默认:yyyy/M/d H:mm:ss</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<int> BulkCopyAsync<T>(List<T> insertList, string dateFormat = "yyyy/M/d H:mm:ss") where T : class
|
||||||
|
{
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(url))
|
||||||
|
{
|
||||||
|
throw new Exception("BulkCopy功能需要启用RestAPI,程序启动时执行:RestAPIExtension.UseQuestDbRestAPI(\"localhost:9000\", \"username\", \"password\")");
|
||||||
|
}
|
||||||
|
var result = 0;
|
||||||
|
var fileName = $"{Guid.NewGuid()}.csv";
|
||||||
|
var filePath = Path.Combine(AppContext.BaseDirectory, fileName);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var client = new HttpClient();
|
||||||
|
var boundary = "---------------" + DateTime.Now.Ticks.ToString("x");
|
||||||
|
var list = new List<Hashtable>();
|
||||||
|
var name = db.EntityMaintenance.GetEntityInfo<T>().DbTableName; //获取表名
|
||||||
|
db.DbMaintenance.GetColumnInfosByTableName(name).ForEach(d =>
|
||||||
|
{
|
||||||
|
if (d.DataType == "TIMESTAMP")
|
||||||
|
{
|
||||||
|
list.Add(new Hashtable()
|
||||||
|
{
|
||||||
|
{ "name", d.DbColumnName },
|
||||||
|
{ "type", d.DataType },
|
||||||
|
{ "pattern", dateFormat}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
list.Add(new Hashtable()
|
||||||
|
{
|
||||||
|
{ "name", d.DbColumnName },
|
||||||
|
{ "type", d.DataType }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var schema = JsonConvert.SerializeObject(list);
|
||||||
|
//写入CSV文件
|
||||||
|
using (var writer = new StreamWriter(filePath))
|
||||||
|
using (var csv = new CsvWriter(writer, CultureInfo.CurrentCulture))
|
||||||
|
{
|
||||||
|
await csv.WriteRecordsAsync(insertList);
|
||||||
|
}
|
||||||
|
|
||||||
|
var httpContent = new MultipartFormDataContent(boundary);
|
||||||
|
if (!string.IsNullOrWhiteSpace(this.authorization))
|
||||||
|
client.DefaultRequestHeaders.Add("Authorization", this.authorization);
|
||||||
|
httpContent.Add(new StringContent(schema), "schema");
|
||||||
|
httpContent.Add(new ByteArrayContent(File.ReadAllBytes(filePath)), "data");
|
||||||
|
//boundary带双引号 可能导致服务器错误情况
|
||||||
|
httpContent.Headers.Remove("Content-Type");
|
||||||
|
httpContent.Headers.TryAddWithoutValidation("Content-Type",
|
||||||
|
"multipart/form-data; boundary=" + boundary);
|
||||||
|
var httpResponseMessage =
|
||||||
|
await client.PostAsync($"{this.url}/imp?name={name}", httpContent);
|
||||||
|
var readAsStringAsync = await httpResponseMessage.Content.ReadAsStringAsync();
|
||||||
|
var splitByLine = QuestDbRestAPHelper.SplitByLine(readAsStringAsync);
|
||||||
|
foreach (var s in splitByLine)
|
||||||
|
{
|
||||||
|
if (s.Contains("Rows"))
|
||||||
|
{
|
||||||
|
var strings = s.Split('|');
|
||||||
|
if (strings[1].Trim() == "Rows imported")
|
||||||
|
{
|
||||||
|
result = Convert.ToInt32(strings[2].Trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File.Delete(filePath);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 批量快速插入
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="that"></param>
|
||||||
|
/// <param name="dateFormat">导入时,时间格式 默认:yyyy/M/d H:mm:ss</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public int BulkCopy<T>(List<T> insertList, string dateFormat = "yyyy/M/d H:mm:ss") where T : class
|
||||||
|
{
|
||||||
|
return BulkCopyAsync(insertList, dateFormat).GetAwaiter().GetResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="CsvHelper" Version="31.0.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\SqlSugar\SqlSugar.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
@ -68,7 +68,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SqlSugar.TDengineCore", "Sq
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "1TDengineTest", "TDengineTest\1TDengineTest.csproj", "{AFBF6813-DA87-4621-9659-5D123234CDDF}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "1TDengineTest", "TDengineTest\1TDengineTest.csproj", "{AFBF6813-DA87-4621-9659-5D123234CDDF}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "2VastbaseTest", "VastbaseTest\2VastbaseTest.csproj", "{FA0F2233-7BD5-49A0-8333-BA471509F2D7}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "2VastbaseTest", "VastbaseTest\2VastbaseTest.csproj", "{FA0F2233-7BD5-49A0-8333-BA471509F2D7}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SqlSugar.QuestDb.RestAPI", "SqlSugar.QuestDb.RestApi\SqlSugar.QuestDb.RestAPI.csproj", "{6DED25D0-660B-468A-AD61-7646345145F5}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@ -440,6 +442,18 @@ Global
|
|||||||
{FA0F2233-7BD5-49A0-8333-BA471509F2D7}.Release|ARM32.Build.0 = Release|Any CPU
|
{FA0F2233-7BD5-49A0-8333-BA471509F2D7}.Release|ARM32.Build.0 = Release|Any CPU
|
||||||
{FA0F2233-7BD5-49A0-8333-BA471509F2D7}.Release|x86.ActiveCfg = Release|Any CPU
|
{FA0F2233-7BD5-49A0-8333-BA471509F2D7}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{FA0F2233-7BD5-49A0-8333-BA471509F2D7}.Release|x86.Build.0 = Release|Any CPU
|
{FA0F2233-7BD5-49A0-8333-BA471509F2D7}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{6DED25D0-660B-468A-AD61-7646345145F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{6DED25D0-660B-468A-AD61-7646345145F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{6DED25D0-660B-468A-AD61-7646345145F5}.Debug|ARM32.ActiveCfg = Debug|Any CPU
|
||||||
|
{6DED25D0-660B-468A-AD61-7646345145F5}.Debug|ARM32.Build.0 = Debug|Any CPU
|
||||||
|
{6DED25D0-660B-468A-AD61-7646345145F5}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{6DED25D0-660B-468A-AD61-7646345145F5}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{6DED25D0-660B-468A-AD61-7646345145F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{6DED25D0-660B-468A-AD61-7646345145F5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{6DED25D0-660B-468A-AD61-7646345145F5}.Release|ARM32.ActiveCfg = Release|Any CPU
|
||||||
|
{6DED25D0-660B-468A-AD61-7646345145F5}.Release|ARM32.Build.0 = Release|Any CPU
|
||||||
|
{6DED25D0-660B-468A-AD61-7646345145F5}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{6DED25D0-660B-468A-AD61-7646345145F5}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@ -452,6 +466,7 @@ Global
|
|||||||
{517D3B1E-EECB-43C3-83B9-33613F45908A} = {88992AAF-146B-4253-9AD7-493E8F415B57}
|
{517D3B1E-EECB-43C3-83B9-33613F45908A} = {88992AAF-146B-4253-9AD7-493E8F415B57}
|
||||||
{7CEB3DFE-8337-4B83-AE6A-D159D73E3CD3} = {88992AAF-146B-4253-9AD7-493E8F415B57}
|
{7CEB3DFE-8337-4B83-AE6A-D159D73E3CD3} = {88992AAF-146B-4253-9AD7-493E8F415B57}
|
||||||
{A8FDDB0E-835A-4042-A955-66A2DB98207D} = {88992AAF-146B-4253-9AD7-493E8F415B57}
|
{A8FDDB0E-835A-4042-A955-66A2DB98207D} = {88992AAF-146B-4253-9AD7-493E8F415B57}
|
||||||
|
{6DED25D0-660B-468A-AD61-7646345145F5} = {88992AAF-146B-4253-9AD7-493E8F415B57}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {230A85B9-54F1-41B1-B1DA-80086581B2B4}
|
SolutionGuid = {230A85B9-54F1-41B1-B1DA-80086581B2B4}
|
||||||
|
Loading…
Reference in New Issue
Block a user