diff --git a/Falcon.SugarApi.Test/BackTaskTest.cs b/Falcon.SugarApi.Test/BackTaskTest.cs
new file mode 100644
index 0000000..4733012
--- /dev/null
+++ b/Falcon.SugarApi.Test/BackTaskTest.cs
@@ -0,0 +1,61 @@
+using Falcon.SugarApi.BackTask;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Threading;
+using System;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Hosting;
+
+namespace Falcon.SugarApi.Test
+{
+ [TestClass]
+ public class BackTaskTest
+ {
+ [TestMethod]
+ public void BackgroundLongTaskTestMethod() {
+ var task = new BackTaskObject();
+ Assert.IsTrue(task.State == 0, "初始化状态错误");
+ var token = new CancellationTokenSource();
+ task.StartAsync(token.Token);
+ Thread.Sleep(1 * 1000);
+ Assert.IsTrue(task.State == 1, "启动状态错误");
+ Thread.Sleep(5 * 1000);
+ task.StopAsync(token.Token).Wait();
+ Thread.Sleep(2 * 1000);
+ Assert.IsTrue(task.State == 2, "停止状态错误");
+ Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss")}:测试完成");
+ }
+ }
+
+ public class BackTaskObject : BackgroundLongTask
+ {
+ public override float RunTimespan => 1;
+ public ILogger Log { get; set; }
+ public int State { get; set; } = 0;
+
+ public BackTaskObject() {
+ this.Log = new TestLog();
+ }
+
+ protected override void OnStop(BackgroundLongTask t) {
+ State = 2;
+ this.Log.LogInformation($"{DateTime.Now.ToString("HH:mm:ss")}:Test OnStop!");
+ base.OnStop(t);
+ }
+
+ protected override void OnStart(BackgroundLongTask t) {
+ State = 1;
+ this.Log.LogInformation($"{DateTime.Now.ToString("HH:mm:ss")}:Test OnStart!");
+ base.OnStart(t);
+ }
+
+ protected override void OnCompleted(BackgroundLongTask t) {
+ this.Log.LogInformation($"{DateTime.Now.ToString("HH:mm:ss")}:Test OnCompleted!");
+ base.OnCompleted(t);
+ }
+
+ protected override void Run() {
+ this.Log.LogInformation($"{DateTime.Now.ToString("HH:mm:ss")}:Test Run!");
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Falcon.SugarApi.Test/Falcon.SugarApi.Test.csproj b/Falcon.SugarApi.Test/Falcon.SugarApi.Test.csproj
new file mode 100644
index 0000000..cdd13dd
--- /dev/null
+++ b/Falcon.SugarApi.Test/Falcon.SugarApi.Test.csproj
@@ -0,0 +1,21 @@
+
+
+
+ net5;net6
+ enable
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Falcon.SugarApi.Test/TestLog.cs b/Falcon.SugarApi.Test/TestLog.cs
new file mode 100644
index 0000000..0372f72
--- /dev/null
+++ b/Falcon.SugarApi.Test/TestLog.cs
@@ -0,0 +1,21 @@
+锘縰sing System;
+using Microsoft.Extensions.Logging;
+
+namespace Falcon.SugarApi.Test
+{
+ ///
+ /// 娴嬭瘯鐢↙ogger瀹炰緥
+ ///
+ public class TestLog : ILogger
+ {
+ public IDisposable BeginScope(TState state) {
+ throw new NotImplementedException();
+ }
+
+ public bool IsEnabled(LogLevel logLevel) => true;
+
+ public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) {
+ Console.WriteLine(state?.ToString());
+ }
+ }
+}
\ No newline at end of file
diff --git a/Falcon.SugarApi.sln b/Falcon.SugarApi.sln
new file mode 100644
index 0000000..1626b14
--- /dev/null
+++ b/Falcon.SugarApi.sln
@@ -0,0 +1,31 @@
+锘
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.1.32228.430
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Falcon.SugarApi", "Falcon.SugarApi\Falcon.SugarApi.csproj", "{0E6BB911-30D2-416F-9B82-23B2C7F0C83F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Falcon.SugarApi.Test", "Falcon.SugarApi.Test\Falcon.SugarApi.Test.csproj", "{EADC8D8F-449C-4C4C-8168-0075B333494B}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {0E6BB911-30D2-416F-9B82-23B2C7F0C83F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0E6BB911-30D2-416F-9B82-23B2C7F0C83F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0E6BB911-30D2-416F-9B82-23B2C7F0C83F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0E6BB911-30D2-416F-9B82-23B2C7F0C83F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EADC8D8F-449C-4C4C-8168-0075B333494B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EADC8D8F-449C-4C4C-8168-0075B333494B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EADC8D8F-449C-4C4C-8168-0075B333494B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EADC8D8F-449C-4C4C-8168-0075B333494B}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {88773585-6316-44D6-B95A-F419F746F361}
+ EndGlobalSection
+EndGlobal
diff --git a/Falcon.SugarApi/ApiDefinistions/ApiBaseOptionController.cs b/Falcon.SugarApi/ApiDefinistions/ApiBaseOptionController.cs
new file mode 100644
index 0000000..eef21ac
--- /dev/null
+++ b/Falcon.SugarApi/ApiDefinistions/ApiBaseOptionController.cs
@@ -0,0 +1,90 @@
+锘縰sing Falcon.SugarApi.DatabaseDefinitions;
+using Microsoft.AspNetCore.Mvc;
+using System;
+using System.Collections.Generic;
+
+namespace Falcon.SugarApi.ApiDefinistions
+{
+ ///
+ /// api鎺ュ彛鍩虹鏁版嵁鎿嶄綔鎺у埗鍣
+ ///
+ /// 鏁版嵁绫诲瀷
+ public abstract class ApiBaseOptionController : ApiControllerBase, IApiBaseControllerOption where T : SugarTableBase, new()
+ {
+ ///
+ /// 瀹炰緥鍖栧熀纭鏁版嵁鎿嶄綔鎺у埗鍣
+ ///
+ /// 鏈嶅姟鎻愪緵鍣
+ public ApiBaseOptionController(IServiceProvider service) : base(service) {
+ }
+ ///
+ /// 鎻掑叆涓鏉℃柊璁板綍
+ ///
+ /// 瑕佸鍔犵殑鏁版嵁
+ /// 澧炲姞浠ュ悗鐨勬暟鎹
+ [HttpPost]
+ public virtual T AddOne(T data) {
+ this.SugarDb.Insert(data, data.CreateBy);
+ return data;
+ }
+ ///
+ /// 鍒犻櫎涓鏉℃暟鎹
+ ///
+ /// 鍒犻櫎鐨勬暟鎹潯浠讹紝鏁版嵁Id
+ /// 鍒犻櫎鍚庣殑鏁版嵁
+ [HttpPost]
+ public virtual T DeleteOne(OneRecoder filter) {
+ var id = filter.Id;
+ this.SugarDb.Delete(id, filter.OptionBy);
+ return this.SugarDb.Queryable().First(m => m.Id == id);
+ }
+ ///
+ /// 淇敼鏁版嵁
+ ///
+ /// 瑕佷慨鏀圭殑鏁版嵁
+ /// 淇敼鍚庣殑鏁版嵁
+ [HttpPost]
+ public virtual T Edit(T data) {
+ this.SugarDb.Update(data, data.UpdateBy);
+ return data;
+ }
+ ///
+ /// 鏌ヨ涓鏉℃暟鎹
+ ///
+ /// 鏁版嵁鏌ヨ鏉′欢锛屾彁渚涙暟鎹甀D
+ /// 鏌ヨ鍒扮殑鏁版嵁闆嗗悎
+ [HttpPost]
+ public virtual IEnumerable GetOne(OneRecoder filter) {
+ return this.SugarDb.Queryable().In(filter.Id).ToList();
+ }
+ ///
+ /// 鑾峰彇涓鏉℃祴璇曟暟鎹紝浠呭湪娴嬭瘯闃舵浣跨敤
+ ///
+ /// 娴嬭瘯鏁版嵁
+ [HttpPost]
+ public virtual T GetTest() {
+ return new T().SetTestModel() as T;
+ }
+ ///
+ /// 鑾峰彇鏁版嵁鍒楄〃
+ ///
+ /// 鍒嗛〉鏉′欢
+ /// 鍒嗛〉鍚庣殑鏁版嵁鍒楄〃
+ /// 鏁版嵁寮傚父
+ [HttpPost]
+ public virtual IEnumerable ListAll(PageData page) {
+ if (page.OrderBy.IsNullOrEmpty()) {
+ throw new ApiException("蹇呴』鎻愪緵OrderBy锛屽垎椤靛皢鎸夋杩涜鎺掑簭銆");
+ }
+ return this.SugarDb.Queryable().OrderBy(page.OrderBy).ToPageList(page.Page, page.PageSize);
+ }
+
+ ///
+ /// 鐩稿叧琛ㄥ垵濮嬪寲
+ ///
+ /// 闇瑕佸垵濮嬪寲鐨勮〃绫诲瀷
+ protected void DataTableInit(params Type[] types) {
+ this.SugarDb.UpdateTableStructure(types);
+ }
+ }
+}
diff --git a/Falcon.SugarApi/ApiDefinistions/ApiControllerBase.cs b/Falcon.SugarApi/ApiDefinistions/ApiControllerBase.cs
new file mode 100644
index 0000000..11bd30a
--- /dev/null
+++ b/Falcon.SugarApi/ApiDefinistions/ApiControllerBase.cs
@@ -0,0 +1,100 @@
+锘縰sing Falcon.SugarApi.DatabaseDefinitions;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using System;
+using System.Text.Encodings.Web;
+using System.Text.Json;
+using System.Text.Unicode;
+
+namespace Falcon.SugarApi.ApiDefinistions
+{
+ ///
+ /// api鎺у埗鍣ㄥ熀绫
+ ///
+ [Area("api")]
+ [ApiController]
+ [Route("api/[Controller]/[Action]")]
+ public abstract class ApiControllerBase : ControllerBase
+ {
+ ///
+ /// 鏃ュ織璁板綍鏈嶅姟
+ ///
+ public ILogger Logger { get; set; }
+ ///
+ /// 鏈嶅姟闆嗗悎
+ ///
+ public IServiceProvider Services { get; set; }
+ ///
+ /// Sugar鏁版嵁搴
+ ///
+ public SugarDbContext SugarDb { get; set; }
+ ///
+ /// 鑾峰彇璇锋眰鐨勬柟娉曞墠缂
+ ///
+ protected virtual string Prefix {
+ get {
+ var con = this.RouteData.Values["controller"];
+ var ac = this.RouteData.Values["action"];
+ return $":{con}:{ac}";
+ }
+ }
+
+ protected ApiControllerBase(IServiceProvider service) {
+ this.Services = service;
+ this.Logger = service.GetService(typeof(ILogger<>).MakeGenericType(GetType())) as ILogger;
+ this.SugarDb = service.GetService();
+ }
+
+ ///
+ /// 璁板綍淇濆瓨璇锋眰鍜屽搷搴旀棩蹇
+ ///
+ /// 璇锋眰淇℃伅绫诲瀷
+ /// 鍝嶅簲淇℃伅绫诲瀷
+ /// 璇锋眰鏁版嵁
+ /// 鍝嶅簲鏁版嵁
+ protected virtual void SaveLogger(TRequest data, TResponse result) {
+ var requestStr = this.JsonSerialize(data);
+ var responseStr = this.JsonSerialize(result);
+ var logmsg = $"{this.Prefix}\n璇锋眰娑堟伅:{requestStr}\n鍝嶅簲娑堟伅{responseStr}";
+ this.Logger.LogInformation(logmsg);
+ }
+
+ ///
+ /// 浠庡璞″簭鍒楀寲瀛楃涓
+ ///
+ /// 瀵硅薄绫诲瀷
+ /// 瑕佸簭鍒楀寲鐨勫璞
+ /// 瀛楃涓
+ protected string JsonSerialize(T obj) {
+ return JsonSerializer.Serialize(obj, new JsonSerializerOptions {
+ Encoder = JavaScriptEncoder.Create(UnicodeRanges.All),
+ });
+ }
+ ///
+ /// 浠庡瓧绗︿覆鍙嶅簭鍒楀寲瀵硅薄
+ ///
+ /// 瀵硅薄鐨勭被鍨
+ /// json瀛楃涓
+ /// 瀵硅薄瀹炰緥
+ protected T JsonDeserialize(string json) {
+ return JsonSerializer.Deserialize(json);
+ }
+
+ ///
+ /// 鎶涘嚭api寮傚父
+ ///
+ /// 寮傚父娑堟伅
+ /// 鍐呴儴寮傚父
+ /// api寮傚父
+ protected virtual void ThrowApiException(string msg, Exception innException)
+ => throw new ApiException(msg, innException);
+ ///
+ /// 鎶涘嚭api寮傚父
+ ///
+ /// 寮傚父娑堟伅
+ /// api寮傚父
+ protected virtual void ThrowApiException(string msg)
+ => throw new ApiException(msg);
+ }
+}
diff --git a/Falcon.SugarApi/ApiDefinistions/ApiException.cs b/Falcon.SugarApi/ApiDefinistions/ApiException.cs
new file mode 100644
index 0000000..727cfdc
--- /dev/null
+++ b/Falcon.SugarApi/ApiDefinistions/ApiException.cs
@@ -0,0 +1,26 @@
+锘縰sing System;
+
+namespace Falcon.SugarApi.ApiDefinistions
+{
+ ///
+ /// api寮傚父鍩虹被
+ ///
+ public class ApiException : Exception
+ {
+ ///
+ /// 閫氳繃寮傚父淇℃伅鍒涘缓寮傚父
+ ///
+ /// 寮傚父淇℃伅
+ public ApiException(string message) : base(message)
+ {
+ }
+ ///
+ /// 閫氳繃寮傚父淇℃伅鍜屽唴閮ㄥ紓甯稿垱寤哄紓甯
+ ///
+ /// 寮傚父淇℃伅
+ /// 鍐呴儴寮傚父
+ public ApiException(string message, Exception innerException) : base(message, innerException)
+ {
+ }
+ }
+}
diff --git a/Falcon.SugarApi/ApiDefinistions/ApiResponseTypeModelProvider.cs b/Falcon.SugarApi/ApiDefinistions/ApiResponseTypeModelProvider.cs
new file mode 100644
index 0000000..8f38acb
--- /dev/null
+++ b/Falcon.SugarApi/ApiDefinistions/ApiResponseTypeModelProvider.cs
@@ -0,0 +1,60 @@
+锘縰sing Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.ApplicationModels;
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Falcon.SugarApi.ApiDefinistions
+{
+ ///
+ /// api鎺ュ彛杩斿洖鍊兼ā鍨嬪畾涔
+ ///
+ public class ApiResponseTypeModelProvider : IApplicationModelProvider
+ {
+ public int Order => 1;
+
+ public void OnProvidersExecuted(ApplicationModelProviderContext context)
+ {
+ }
+
+ public void OnProvidersExecuting(ApplicationModelProviderContext context)
+ {
+ foreach (ControllerModel controller in context.Result.Controllers)
+ {
+ foreach (ActionModel action in controller.Actions)
+ {
+ if (!isApiAction(action))
+ {
+ continue;
+ }
+ var art = action.ActionMethod.ReturnType;
+ Type returnType =
+ art.IsGenericType && art.IsAssignableFrom(typeof(Task<>)) ? art.GenericTypeArguments[0].GetGenericArguments()[0] :
+ art;
+ action.Filters.Add(new ProducesResponseTypeAttribute(returnType, StatusCodes.Status200OK));
+ action.Filters.Add(new ProducesResponseTypeAttribute(typeof(ExceptionModel), StatusCodes.Status400BadRequest));
+ }
+ }
+ }
+
+ ///
+ /// 鏂规硶鏄惁涓篴pi鏂规硶
+ ///
+ /// Action妯″瀷
+ /// 鏄痑pi鏂规硶杩斿洖true锛屽惁鍒檉alse
+ protected static bool isApiAction(ActionModel am)
+ {
+ if (am.Controller.Attributes.Any(c => c is ApiControllerAttribute))
+ {
+ return true;
+ }
+ if (am.Attributes.Any(c => c is ApiControllerAttribute))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ }
+}
diff --git a/Falcon.SugarApi/ApiDefinistions/ExceptionModel.cs b/Falcon.SugarApi/ApiDefinistions/ExceptionModel.cs
new file mode 100644
index 0000000..d64f324
--- /dev/null
+++ b/Falcon.SugarApi/ApiDefinistions/ExceptionModel.cs
@@ -0,0 +1,21 @@
+锘縩amespace Falcon.SugarApi.ApiDefinistions
+{
+ ///
+ /// 寮傚父杩斿洖妯″瀷
+ ///
+ public class ExceptionModel
+ {
+ ///
+ /// 寮傚父缂栧彿
+ ///
+ public string Id { get; set; }
+ ///
+ /// 寮傚父淇℃伅
+ ///
+ public string Message { get; set; }
+ ///
+ /// 寮傚父鍙戠敓鏃堕棿
+ ///
+ public string CreateDateTime { get; set; }
+ }
+}
diff --git a/Falcon.SugarApi/ApiDefinistions/HttpResponseExceptionFilter.cs b/Falcon.SugarApi/ApiDefinistions/HttpResponseExceptionFilter.cs
new file mode 100644
index 0000000..5dbf0d0
--- /dev/null
+++ b/Falcon.SugarApi/ApiDefinistions/HttpResponseExceptionFilter.cs
@@ -0,0 +1,52 @@
+锘縰sing Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Microsoft.Extensions.Logging;
+using System;
+using System.Text;
+
+namespace Falcon.SugarApi.ApiDefinistions
+{
+ public class HttpResponseExceptionFilter : IActionFilter, IOrderedFilter
+ {
+ ///
+ /// 鏃ュ織璁板綍鍣
+ ///
+ public ILogger Logger { get; set; }
+
+ public HttpResponseExceptionFilter(ILogger logger)
+ {
+ this.Logger = logger;
+ }
+
+ public int Order { get; } = int.MaxValue - 10;
+
+ public void OnActionExecuting(ActionExecutingContext context) { }
+
+ public void OnActionExecuted(ActionExecutedContext context)
+ {
+ if (context.Exception == null || context.ExceptionHandled)
+ {
+ return;
+ }
+ var exception = context.Exception;
+ var now = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
+ var model = new ExceptionModel
+ {
+ Id = Guid.NewGuid().ToString(),
+ CreateDateTime = now,
+ Message = exception.Message,
+ };
+ if (exception is ApiException)
+ {
+ context.Result = new ObjectResult(model) { StatusCode = 400, };
+ context.ExceptionHandled = true;
+ }
+ var logmsg = new StringBuilder();
+ logmsg.AppendLine($"寮傚父缂栧彿:{model.Id}");
+ logmsg.AppendLine($"閿欒淇℃伅:{model.Message}");
+ logmsg.AppendLine($"璇︾粏淇℃伅:");
+ logmsg.AppendLine($"{exception}");
+ this.Logger.LogError(logmsg.ToString());
+ }
+ }
+}
diff --git a/Falcon.SugarApi/ApiDefinistions/IApiBaseControllerOption.cs b/Falcon.SugarApi/ApiDefinistions/IApiBaseControllerOption.cs
new file mode 100644
index 0000000..75347b1
--- /dev/null
+++ b/Falcon.SugarApi/ApiDefinistions/IApiBaseControllerOption.cs
@@ -0,0 +1,48 @@
+锘縰sing Falcon.SugarApi.DatabaseDefinitions;
+using System.Collections.Generic;
+
+namespace Falcon.SugarApi.ApiDefinistions
+{
+ ///
+ /// 瀹氫箟api鍩虹瀹炵幇鏂规硶
+ ///
+ /// api瀵瑰簲鐨勬暟鎹被鍨
+ public interface IApiBaseControllerOption where T : SugarTableBase
+ {
+ ///
+ /// 澧炲姞鏁版嵁
+ ///
+ /// 鏁版嵁瀹炰綋
+ /// 澧炲姞鍚庣殑鏁版嵁瀹炰綋
+ T AddOne(T data);
+ ///
+ /// 鏍规嵁id鍒犻櫎涓涓暟鎹褰
+ ///
+ /// 鍒犻櫎鏉′欢锛屼粎鎻愪緵鏁版嵁id
+ /// 鍒犻櫎鍚庣殑鏁版嵁瀹炰綋
+ T DeleteOne(OneRecoder filter);
+ ///
+ /// 淇敼瀹炰綋鏁版嵁
+ ///
+ /// 鏁版嵁瀹炰綋
+ /// 淇敼鍚庣殑鏁版嵁瀹炰綋
+ T Edit(T data);
+ ///
+ /// 鑾峰彇涓涓祴璇曟暟鎹
+ ///
+ /// 涓涓祴璇曡褰
+ T GetTest();
+ ///
+ /// 鍒嗛〉鑾峰彇鏁版嵁
+ ///
+ /// 鍒嗛〉鏁版嵁
+ /// 鏁版嵁鍒楄〃
+ IEnumerable ListAll(PageData page);
+ ///
+ /// 鏍规嵁id鑾峰彇涓鏉¤褰
+ ///
+ /// 鍒犻櫎鏉′欢锛屼粎鎻愪緵鏁版嵁id
+ /// 鍒犻櫎鍚庣殑鏁版嵁鍒楄〃
+ IEnumerable GetOne(OneRecoder filter);
+ }
+}
\ No newline at end of file
diff --git a/Falcon.SugarApi/ApiDefinistions/OneRecoder.cs b/Falcon.SugarApi/ApiDefinistions/OneRecoder.cs
new file mode 100644
index 0000000..dbb5b42
--- /dev/null
+++ b/Falcon.SugarApi/ApiDefinistions/OneRecoder.cs
@@ -0,0 +1,19 @@
+锘縰sing System;
+
+namespace Falcon.SugarApi.ApiDefinistions
+{
+ ///
+ /// 涓鏉¤褰
+ ///
+ public class OneRecoder
+ {
+ ///
+ /// 鏁版嵁ID
+ ///
+ public Guid Id { get; set; }
+ ///
+ /// 鎿嶄綔鍛
+ ///
+ public string OptionBy { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Falcon.SugarApi/ApiDefinistions/PageData.cs b/Falcon.SugarApi/ApiDefinistions/PageData.cs
new file mode 100644
index 0000000..385a2cb
--- /dev/null
+++ b/Falcon.SugarApi/ApiDefinistions/PageData.cs
@@ -0,0 +1,21 @@
+锘縩amespace Falcon.SugarApi.ApiDefinistions
+{
+ ///
+ /// 鍒嗛〉鏁版嵁
+ ///
+ public class PageData
+ {
+ ///
+ /// 椤靛彿鐮
+ ///
+ public int Page { get; set; } = 0;
+ ///
+ /// 椤靛ぇ灏
+ ///
+ public int PageSize { get; set; } = 50;
+ ///
+ /// 鎺掑簭渚濇嵁 鍒楀悕 desc鍊掑簭
+ ///
+ public string OrderBy { get; set; } = "ID DESC";
+ }
+}
\ No newline at end of file
diff --git a/Falcon.SugarApi/BackTask/BackgroundLongTask.cs b/Falcon.SugarApi/BackTask/BackgroundLongTask.cs
new file mode 100644
index 0000000..c494f35
--- /dev/null
+++ b/Falcon.SugarApi/BackTask/BackgroundLongTask.cs
@@ -0,0 +1,73 @@
+锘縰sing Microsoft.Extensions.Hosting;
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Falcon.SugarApi.BackTask
+{
+ ///
+ /// 闀挎椂闂存墽琛岀殑鍚庡彴浠诲姟
+ ///
+ public abstract class BackgroundLongTask : BackgroundService
+ {
+ ///
+ /// 瑕佹墽琛岀殑浠诲姟
+ ///
+ protected abstract void Run();
+ ///
+ /// 鎵ц鏃堕棿闂撮殧
+ ///
+ public abstract float RunTimespan { get; }
+ ///
+ /// 鍚庡彴浠诲姟寮濮
+ ///
+ protected virtual void OnStart(BackgroundLongTask t) { }
+ ///
+ /// 鍚庡彴浠诲姟鍋滄
+ ///
+ protected virtual void OnStop(BackgroundLongTask t) { }
+ ///
+ /// 瀹屾垚涓娆℃墽琛
+ ///
+ protected virtual void OnCompleted(BackgroundLongTask t) { }
+
+ ///
+ /// 鐢ㄤ簬瀹氭湡鎵ц浠诲姟鐨勫鎵
+ ///
+ private Action action;
+
+ private CancellationTokenSource TokenSource { get; set; } = new();
+
+ ///
+ /// 鏋勯犱竴涓悗鍙伴暱鏈熶换鍔
+ ///
+ public BackgroundLongTask() {
+ action = async () => {
+ OnStart(this);
+ while (!TokenSource.Token.IsCancellationRequested) {
+ await Task.Delay(TimeSpan.FromSeconds(RunTimespan))
+ .ContinueWith(wt => { Run(); }).ContinueWith(wt => OnCompleted(this));
+ }
+ OnStop(this);
+ };
+ }
+ ///
+ /// 鏈嶅姟鍣ㄥ惎鍔ㄦ椂鎵ц
+ ///
+ /// 閫鍑轰俊鍙
+ ///
+ protected override Task ExecuteAsync(CancellationToken stoppingToken) {
+ _ = Task.Factory.StartNew(action, stoppingToken);
+ return Task.CompletedTask;
+ }
+ ///
+ /// 鍋滄浠诲姟
+ ///
+ /// 閫鍑烘爣璁
+ /// 浠诲姟
+ public override Task StopAsync(CancellationToken cancellationToken) {
+ this.TokenSource.Cancel();
+ return base.StopAsync(cancellationToken);
+ }
+ }
+}
diff --git a/Falcon.SugarApi/BackTask/IServiceCollectionExtend.cs b/Falcon.SugarApi/BackTask/IServiceCollectionExtend.cs
new file mode 100644
index 0000000..09230c6
--- /dev/null
+++ b/Falcon.SugarApi/BackTask/IServiceCollectionExtend.cs
@@ -0,0 +1,18 @@
+锘縰sing Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+
+namespace Falcon.SugarApi.BackTask
+{
+ public static class IServiceCollectionExtend
+ {
+ ///
+ /// 娉ㄥ唽BackgroundLongTask鍚庡彴浠诲姟銆
+ ///
+ /// 鏈嶅姟闆嗗悎
+ /// 鏈嶅姟闆嗗悎
+ public static IServiceCollection AddBackgroundLongTask(this IServiceCollection services)
+ where T : BackgroundLongTask {
+ return services.AddHostedService();
+ }
+ }
+}
diff --git a/Falcon.SugarApi/DatabaseDefinitions/ICreateNew.cs b/Falcon.SugarApi/DatabaseDefinitions/ICreateNew.cs
new file mode 100644
index 0000000..15b0649
--- /dev/null
+++ b/Falcon.SugarApi/DatabaseDefinitions/ICreateNew.cs
@@ -0,0 +1,14 @@
+锘縩amespace Falcon.SugarApi.DatabaseDefinitions
+{
+ ///
+ /// 瀹炰綋绫绘敮鎸佹柊寤烘暟鎹柟娉
+ ///
+ public interface ICreateNew
+ {
+ ///
+ /// 鍒涘缓鏂版暟鎹疄浣
+ ///
+ /// 鍒涘缓浜
+ void CreateNew(string createBy);
+ }
+}
\ No newline at end of file
diff --git a/Falcon.SugarApi/DatabaseDefinitions/IDelete.cs b/Falcon.SugarApi/DatabaseDefinitions/IDelete.cs
new file mode 100644
index 0000000..b98acb2
--- /dev/null
+++ b/Falcon.SugarApi/DatabaseDefinitions/IDelete.cs
@@ -0,0 +1,14 @@
+锘縩amespace Falcon.SugarApi.DatabaseDefinitions
+{
+ ///
+ /// 瀹炰綋杞垹闄ゆ柟娉
+ ///
+ public interface IDelete
+ {
+ ///
+ /// 鍒犻櫎鏈潯鏁版嵁銆傝蒋鍒犻櫎
+ ///
+ /// 鍒犻櫎浜
+ void Delete(string deleteBy);
+ }
+}
\ No newline at end of file
diff --git a/Falcon.SugarApi/DatabaseDefinitions/IModify.cs b/Falcon.SugarApi/DatabaseDefinitions/IModify.cs
new file mode 100644
index 0000000..34d3dee
--- /dev/null
+++ b/Falcon.SugarApi/DatabaseDefinitions/IModify.cs
@@ -0,0 +1,14 @@
+锘縩amespace Falcon.SugarApi.DatabaseDefinitions
+{
+ ///
+ /// 瀹炰綋鏀寔淇敼鏂规硶
+ ///
+ public interface IModify
+ {
+ ///
+ /// 鏇存柊鏁版嵁鎻愮ず
+ ///
+ /// 淇敼浜
+ void Modify(string updateBy);
+ }
+}
\ No newline at end of file
diff --git a/Falcon.SugarApi/DatabaseDefinitions/MyConnectionConfig.cs b/Falcon.SugarApi/DatabaseDefinitions/MyConnectionConfig.cs
new file mode 100644
index 0000000..3f6a19d
--- /dev/null
+++ b/Falcon.SugarApi/DatabaseDefinitions/MyConnectionConfig.cs
@@ -0,0 +1,48 @@
+锘縰sing SqlSugar;
+using System;
+using System.ComponentModel.DataAnnotations;
+using System.Reflection;
+using System.Linq;
+
+namespace Falcon.SugarApi.DatabaseDefinitions
+{
+ ///
+ /// SqlSugar鏁版嵁搴撹繛鎺ラ厤缃
+ ///
+ public class SugarConnectionConfig : ConnectionConfig
+ {
+ ///
+ /// 鏄惁浣跨敤log
+ ///
+ public bool Log { get; set; }
+
+ public SugarConnectionConfig() {
+ this.ConfigureExternalServices ??= new ConfigureExternalServices { };
+ this.ConfigureExternalServices.EntityService += (p, c) => {
+ var pt = p.PropertyType;
+ if (pt.GetCustomAttribute() != null) {
+ c.IsNullable = false;
+ return;
+ }
+ if (pt.IsGenericType && pt.GetGenericTypeDefinition() == typeof(Nullable<>)) {
+ c.IsNullable = true;
+ return;
+ }
+ //var sc = pt.GetCustomAttribute();
+ //if (sc != null) {
+ // c.IsNullable = sc.IsNullable;
+ //}
+ var isNullableTypes = new Type[] { typeof(string) };
+ if (isNullableTypes.Contains(pt)) {
+ c.IsNullable = true;
+ }
+ else {
+ c.IsNullable = false;
+ }
+ //if (pt == typeof(string) && pt.GetCustomAttribute() == null) {
+ // c.IsNullable = true;
+ //}
+ };
+ }
+ }
+}
diff --git a/Falcon.SugarApi/DatabaseDefinitions/RecordStetus.cs b/Falcon.SugarApi/DatabaseDefinitions/RecordStetus.cs
new file mode 100644
index 0000000..a35c550
--- /dev/null
+++ b/Falcon.SugarApi/DatabaseDefinitions/RecordStetus.cs
@@ -0,0 +1,17 @@
+锘縩amespace Falcon.SugarApi.DatabaseDefinitions
+{
+ ///
+ /// 璁板綍鐘舵
+ ///
+ public static class RecordStetus
+ {
+ ///
+ /// 鏈夋晥璁板綍
+ ///
+ public static string Effective => "鏈夋晥";
+ ///
+ /// 鏃犳晥锛屽凡鍒犻櫎璁板綍
+ ///
+ public static string Invalid => "鏃犳晥";
+ }
+}
diff --git a/Falcon.SugarApi/DatabaseDefinitions/SugarDbContext.cs b/Falcon.SugarApi/DatabaseDefinitions/SugarDbContext.cs
new file mode 100644
index 0000000..69cd80f
--- /dev/null
+++ b/Falcon.SugarApi/DatabaseDefinitions/SugarDbContext.cs
@@ -0,0 +1,193 @@
+锘縰sing Microsoft.Extensions.Logging;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Falcon.SugarApi.DatabaseDefinitions
+{
+ ///
+ /// Sugar鏁版嵁搴撲笂涓嬫枃
+ ///
+ public class SugarDbContext : SqlSugarClient
+ {
+ ///
+ /// 閫氳繃閾炬帴閰嶇疆ConnectionConfig鏋勯燬qlSugarClient鏁版嵁涓婁笅鏂
+ ///
+ ///
+ /// 鏃ュ織璁板綍鍣
+ public SugarDbContext(SugarConnectionConfig config, ILogger logger) : base(config) {
+ this.Logger = logger;
+ if (config.Log) {
+ this.Aop.OnLogExecuting = (string sql, SugarParameter[] paras) => {
+ StringBuilder sb = new();
+ sb.AppendLine(sql);
+ sb.AppendLine(this.Utilities.SerializeObject(paras.ToDictionary(it => it.ParameterName, it => it.Value)));
+ this.Logger.LogInformation(sb.ToString());
+ };
+ }
+ }
+ ///
+ /// 鏃ュ織璁板綍
+ ///
+ public ILogger Logger { get; }
+
+ #region 鎻掑叆
+ ///
+ /// 鍦ㄦ暟鎹簱涓彃鍏ユ暟鎹
+ ///
+ /// 鏁版嵁瀹炰綋绫诲瀷
+ /// 瑕佹彃鍏ョ殑鏁版嵁鍒楄〃
+ /// 鍒涘缓浜
+ public void Insert(List data, string createBy) where T : class, new() {
+ foreach (var i in data) {
+ if (i is ICreateNew cn) {
+ cn.CreateNew(createBy);
+ }
+ }
+ this.Insertable(data).ExecuteCommand();
+ }
+
+ ///
+ /// 鍦ㄦ暟鎹簱涓彃鍏ユ暟鎹
+ ///
+ /// 鏁版嵁妯″瀷
+ /// 瑕佹彃鍏ョ殑鏁版嵁
+ /// 鍒涘缓浜
+ public void Insert(T data, string createBy) where T : class, new() {
+ this.Insert(new List { data }, createBy);
+ }
+
+ #endregion
+
+ #region 鏇存柊
+ ///
+ /// 鍦ㄦ暟鎹簱涓洿鏂版暟鎹
+ ///
+ /// 鏁版嵁妯″瀷
+ /// 瑕佹洿鏂扮殑鏁版嵁
+ /// 鏇存柊浜
+ public List Update(List data, string updateBy) where T : class, new() {
+ foreach (var i in data) {
+ if (i is IModify cn) {
+ cn.Modify(updateBy);
+ }
+ }
+ this.Updateable(data).ExecuteCommand();
+ return data;
+ }
+
+ ///
+ /// 淇敼鏁版嵁
+ ///
+ /// 鏁版嵁妯″瀷
+ /// 瑕佹洿鏂扮殑鏁版嵁
+ /// 鏇存柊浜
+ public T Update(T data, string updateBy) where T : class, new() {
+ this.Update(new List { data }, updateBy);
+ return data;
+ }
+
+ #endregion
+
+ #region 杞垹闄
+ ///
+ /// 鏍规嵁涓婚敭璋冪敤IDelete瀹炵幇鍒犻櫎鏁版嵁璁板綍,杞垹闄ゅ苟闈炵湡姝e垹闄ゆ暟鎹
+ ///
+ /// 鏁版嵁瀹炰綋绫诲瀷锛屽繀椤荤户鎵胯嚜SugarTableBase
+ /// 瑕佸垹闄ょ殑鏁版嵁id
+ /// 鍒犻櫎浜
+ public void Delete(Guid id, string deleteBy) where T : SugarTableBase, new() {
+ var data = new T();
+ data.Delete(deleteBy);
+ this.Updateable()
+ .Where(m => m.Id == id)
+ .SetColumns(m => m.Status == data.Status)
+ .SetColumns(m => m.UpdateBy == data.UpdateBy)
+ .SetColumns(m => m.UpdateTime == data.UpdateTime)
+ .ExecuteCommand();
+ }
+
+ ///
+ /// 鎵归噺杞垹闄ゅ璞″垪琛紝璋冪敤瀹炰綋鐨処Delete瀹炵幇鍒犻櫎瀹炰綋銆
+ ///
+ /// 瀹炰綋鐨勭被鍨
+ /// 瀹炰綋瀵硅薄鍒楄〃
+ /// 鍒犻櫎浜
+ /// 鍒犻櫎鍚庣殑瀹炰綋鍒楄〃
+ public List Delete(List data, string deleteBy) where T : class, new() {
+ foreach (var item in data) {
+ if (item is IDelete d) {
+ d.Delete(deleteBy);
+ }
+ }
+ this.Updateable(data).ExecuteCommand();
+ return data;
+ }
+ ///
+ /// 瀵硅薄杞垹闄わ紝璋冪敤瀹炰綋鐨処Delete瀹炵幇鍒犻櫎瀹炰綋銆
+ ///
+ /// 瀹炰綋鐨勭被鍨
+ /// 瀹炰綋瀵硅薄
+ /// 鍒犻櫎浜
+ /// 鍒犻櫎鍚庣殑瀵硅薄
+ public T Delete(T data, string deleteBy) where T : class, new() {
+ this.Delete(new List { data }, deleteBy);
+ return data;
+ }
+
+ #endregion
+
+ #region 鍒濆鍖
+ ///
+ /// 宸茬粡鍒濆鍖栫殑绫诲瀷鍒楄〃
+ ///
+ private static readonly List InitdTable = new();
+
+ ///
+ /// 鍗囩骇鏁版嵁搴撹〃鏋舵瀯骞跺浠借〃鍜屾暟鎹
+ ///
+ /// 瑕佸崌绾х殑琛ㄦā鍨
+ public void UpdateTableStructure(params Type[] types) {
+ for (int i = 0; i < types.Length; i++) {
+ var type = types[i];
+ if (!InitdTable.Any(m => m == type.FullName)) {
+ this.CodeFirst.BackupTable().SetStringDefaultLength(200).InitTables(type);
+ InitdTable.Add(type.FullName);
+ }
+ }
+
+ }
+
+ ///
+ /// 鍗囩骇鏁版嵁搴撹〃鏋舵瀯骞跺浠借〃鍜屾暟鎹
+ ///
+ /// 琛ㄦā鍨
+ public void UpdateTableStructure() {
+ this.UpdateTableStructure(typeof(TableType));
+ }
+
+ #endregion
+
+ #region 鎵ц瀛樺偍杩囩▼
+ public IAdo GetAdo() {
+ return this.Ado.UseStoredProcedure();
+ }
+
+ ///
+ /// 鑾峰彇涓涓狾racle娓告爣绫诲瀷鍙傛暟鐢ㄤ綔杩斿洖鍊
+ ///
+ ///
+ ///
+ public SugarParameter OracleRefCursor(string name = "v_data") =>
+ new(name, null, true) { IsRefCursor = true };
+
+
+ public object GetParameters(T data) {
+ //return SqlSugarTool.GetParameters(new { pageStart = 1, pageEnd = 5, recordCount = 0 });
+ throw new NotSupportedException();
+ }
+ #endregion
+ }
+}
diff --git a/Falcon.SugarApi/DatabaseDefinitions/SugarTableBase.cs b/Falcon.SugarApi/DatabaseDefinitions/SugarTableBase.cs
new file mode 100644
index 0000000..6eabec9
--- /dev/null
+++ b/Falcon.SugarApi/DatabaseDefinitions/SugarTableBase.cs
@@ -0,0 +1,119 @@
+锘縰sing SqlSugar;
+using System;
+using System.Reflection;
+
+namespace Falcon.SugarApi.DatabaseDefinitions
+{
+ ///
+ /// 琛ㄥ熀绫汇備竴鑸〃搴旇缁ф壙姝ょ被
+ ///
+ public abstract class SugarTableBase : ICreateNew, IModify, IDelete
+ {
+ ///
+ /// 涓婚敭
+ ///
+ [SugarColumn(IsPrimaryKey = true, ColumnDescription = "涓婚敭")]
+ public Guid Id { get; set; } = Guid.NewGuid();
+ ///
+ /// 鍒涘缓浜
+ ///
+ [SugarColumn(IsOnlyIgnoreUpdate = true, IsNullable = false, ColumnDescription = "棣栨鍒涘缓浜")]
+ public string CreateBy { get; set; }
+ ///
+ /// 鍒涘缓鏃堕棿
+ ///
+ [SugarColumn(IsOnlyIgnoreUpdate = true, IsNullable = false, ColumnDescription = "棣栨鍒涘缓鏃堕棿")]
+ public DateTime CreateTime { get; set; } = DateTime.Now;
+ ///
+ /// 鏇存柊浜
+ ///
+ [SugarColumn(IsNullable = false, ColumnDescription = "鏈杩戞洿鏂颁汉")]
+ public string UpdateBy { get; set; }
+ ///
+ /// 鏇存柊鏃堕棿
+ ///
+ [SugarColumn(IsNullable = false, ColumnDescription = "鏈鏂版洿鏂版椂闂")]
+ public DateTime UpdateTime { get; set; } = DateTime.Now;
+ ///
+ /// 璁板綍鐘舵
+ ///
+ [SugarColumn(IsNullable = false, ColumnDescription = "璁板綍鐘舵併傛湁鏁 鏃犳晥")]
+ public string Status { get; set; } = "鏈夋晥";
+
+ ///
+ /// 鍒涘缓鏂版暟鎹褰曘
+ ///
+ /// 鍒涘缓浜
+ public virtual void CreateNew(string createBy) {
+ this.Id = Guid.NewGuid();
+ this.CreateBy = createBy;
+ this.CreateTime = DateTime.Now;
+ this.UpdateBy = this.CreateBy;
+ this.UpdateTime = this.CreateTime;
+ this.Status = RecordStetus.Effective;
+ }
+
+ ///
+ /// 淇敼瀹炰綋鏁版嵁
+ ///
+ /// 淇敼浜
+ public virtual void Modify(string updateBy) {
+ this.UpdateBy = updateBy;
+ this.UpdateTime = DateTime.Now;
+ }
+ ///
+ /// 鍒犻櫎鏈潯鏁版嵁銆傝蒋鍒犻櫎
+ ///
+ /// 鍒犻櫎浜
+ public virtual void Delete(string deleteBy) {
+ this.UpdateBy = deleteBy;
+ this.UpdateTime = DateTime.Now;
+ this.Status = RecordStetus.Invalid;
+ }
+
+ ///
+ /// 灏嗗疄浣撹缃负娴嬭瘯鐢ㄦ暟鎹!鐢熸垚娴嬭瘯鏁版嵁灏嗕涪澶卞師鏈夋暟鎹紝鍙湪娴嬭瘯鎯呭喌涓嬩娇鐢
+ ///
+ public virtual SugarTableBase SetTestModel() {
+ foreach (PropertyInfo pro in this.GetType().GetProperties()) {
+ if (pro.Name == "Id") {
+ this.Id = Guid.NewGuid();
+ continue;
+ }
+ if (pro.Name == "CreateBy" || pro.Name == "UpdateBy") {
+ pro.SetValue(this, "admin");
+ continue;
+ }
+ if (pro.Name == "CreateTime" || pro.Name == "UpdateTime") {
+ pro.SetValue(this, DateTime.Now);
+ continue;
+ }
+ if (pro.Name == "Status") {
+ this.Status = "Effective";
+ continue;
+ }
+ if (pro.CanWrite && pro.PropertyType == typeof(string)) {
+ pro.SetValue(this, pro.Name);
+ continue;
+ }
+ }
+ return this;
+ }
+
+ ///
+ /// 璁剧疆璁板綍鏈夋晥
+ ///
+ public virtual SugarTableBase SetEnable() {
+ this.Status = RecordStetus.Effective;
+ return this;
+ }
+ ///
+ /// 璁剧疆璁板綍鏃犳晥
+ ///
+ public virtual SugarTableBase SetDisable() {
+ this.Status = RecordStetus.Invalid;
+ return this;
+ }
+
+ }
+}
diff --git a/Falcon.SugarApi/Falcon.SugarApi.csproj b/Falcon.SugarApi/Falcon.SugarApi.csproj
new file mode 100644
index 0000000..4b476b3
--- /dev/null
+++ b/Falcon.SugarApi/Falcon.SugarApi.csproj
@@ -0,0 +1,26 @@
+
+
+
+ net5;net6
+ disable
+ enable
+ Falcon.SugarApi鍩虹瀹氫箟
+ bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml
+ true
+ 1.0.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Falcon.SugarApi/IServiceCollectionExtend.cs b/Falcon.SugarApi/IServiceCollectionExtend.cs
new file mode 100644
index 0000000..f28e8f2
--- /dev/null
+++ b/Falcon.SugarApi/IServiceCollectionExtend.cs
@@ -0,0 +1,51 @@
+锘縰sing Falcon.SugarApi.ApiDefinistions;
+using Falcon.SugarApi.DatabaseDefinitions;
+using Microsoft.AspNetCore.Mvc.ApplicationModels;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using System;
+
+namespace Falcon.SugarApi
+{
+ public static class IServiceCollectionExtend
+ {
+ ///
+ /// 娉ㄥ唽Falcon.Sugar鐩稿叧api鏂规硶鍜屾暟鎹簱涓婁笅鏂囥
+ ///
+ /// 鏈嶅姟闆嗗悎
+ /// 鏁版嵁涓婁笅鏂囬厤缃妭鐐
+ /// 鏈嶅姟闆嗗悎
+ public static IServiceCollection AddSugarApiWithDbContext(this IServiceCollection services, SugarConnectionConfig config) {
+ return services.AddSugarApiDbContext(config).AddApiReturnModelProvider();
+ }
+
+ ///
+ /// 娉ㄥ唽sugarDbcontext鏁版嵁涓婁笅鏂
+ ///
+ /// 鏈嶅姟闆嗗悎
+ /// 鐢ㄤ簬鐢熸垚閰嶇疆瀹炰緥鐨勬柟娉
+ /// 鏈嶅姟闆嗗悎
+ public static IServiceCollection AddSugarApiDbContext(this IServiceCollection services, Func builder) {
+ return services.AddSingleton(p => builder(p)).AddTransient();
+ }
+
+ ///
+ /// 娉ㄥ唽sugarDbcontext鏁版嵁涓婁笅鏂
+ ///
+ /// 鏈嶅姟闆嗗悎
+ /// 鏁版嵁搴撻厤缃
+ /// 鏈嶅姟闆嗗悎
+ public static IServiceCollection AddSugarApiDbContext(this IServiceCollection service, SugarConnectionConfig config) {
+ return service.AddSingleton(config).AddTransient();
+ }
+ ///
+ /// 娉ㄥ唽api杩斿洖缁撴灉妯″瀷鎻愪緵鍣
+ ///
+ /// 鏈嶅姟闆嗗悎
+ /// 鏈嶅姟闆嗗悎
+ public static IServiceCollection AddApiReturnModelProvider(this IServiceCollection services) {
+ services.TryAddEnumerable(ServiceDescriptor.Transient());
+ return services;
+ }
+ }
+}
diff --git a/Falcon.SugarApi/StringExtend.cs b/Falcon.SugarApi/StringExtend.cs
new file mode 100644
index 0000000..3b56fdd
--- /dev/null
+++ b/Falcon.SugarApi/StringExtend.cs
@@ -0,0 +1,21 @@
+锘縩amespace Falcon.SugarApi
+{
+ ///
+ /// 瀛楃涓叉墿灞
+ ///
+ internal static class StringExtend
+ {
+ ///
+ /// 瀛楃涓叉槸鍚︿负绌烘垨null
+ ///
+ /// 瀛楃涓
+ /// 绌烘垨null涓篢rue锛屽惁鍒橣alse
+ public static bool IsNullOrEmpty(this string str) => str == null || string.IsNullOrEmpty(str);
+ ///
+ /// 瀛楃涓叉槸鍚︿笉涓虹┖鎴杗ull
+ ///
+ /// 瀛楃涓
+ /// 涓嶪sNullOrEmpty鐩稿弽
+ public static bool IsNotNullOrEmpty(this string str) => !str.IsNullOrEmpty();
+ }
+}