Bläddra i källkod

修改文件冲突

zhouj1203@hotmail.com 4 år sedan
förälder
incheckning
096cfe4172
100 ändrade filer med 3594 tillägg och 1148 borttagningar
  1. 264 0
      TEAMModelFunction/.gitignore
  2. 35 0
      TEAMModelFunction/MonitorCosmosDB.cs
  3. 17 0
      TEAMModelFunction/MonitorServicesBus.cs
  4. 8 0
      TEAMModelFunction/Properties/serviceDependencies.json
  5. 9 0
      TEAMModelFunction/Properties/serviceDependencies.local.json
  6. 19 0
      TEAMModelFunction/Startup.cs
  7. 25 0
      TEAMModelFunction/TEAMModelFunction.csproj
  8. 11 0
      TEAMModelFunction/host.json
  9. 1 1
      TEAMModelGrpc/Models/ListPid.cs
  10. 0 77
      TEAMModelGrpc/Services/BlobSASService.cs
  11. 3 3
      TEAMModelGrpc/Services/ClassroomService.cs
  12. 3 3
      TEAMModelGrpc/Services/ClassroomStudentService.cs
  13. 3 3
      TEAMModelGrpc/Services/CourseService.cs
  14. 3 3
      TEAMModelGrpc/Services/HomeWorkService.cs
  15. 0 93
      TEAMModelGrpc/Services/KnowledgeService.cs
  16. 0 124
      TEAMModelGrpc/Services/SyllabusService.cs
  17. 0 82
      TEAMModelGrpc/Services/VolumeService.cs
  18. 9 14
      TEAMModelGrpc/Startup.cs
  19. 0 115
      TEAMModelGrpc/TEAMModelOS.GRPC.xml
  20. 1 0
      TEAMModelOS.SDK/Context/Attributes/Azure/CosmosDBAttribute.cs
  21. 61 0
      TEAMModelOS.SDK/Context/Configuration/Option.cs
  22. 5 5
      TEAMModelOS.SDK/Context/Filters/HttpGlobalExceptionInvoke.cs
  23. 743 0
      TEAMModelOS.SDK/DI/AzureCosmos/AzureCosmosExtensions.cs
  24. 207 0
      TEAMModelOS.SDK/DI/AzureCosmos/AzureCosmosFactory.cs
  25. 20 0
      TEAMModelOS.SDK/DI/AzureCosmos/AzureCosmosFactoryExtensions.cs
  26. 14 0
      TEAMModelOS.SDK/DI/AzureCosmos/AzureCosmosFactoryOptions.cs
  27. 18 0
      TEAMModelOS.SDK/DI/AzureCosmos/Inner/AzureCosmosDict.cs
  28. 6 4
      TEAMModelOS.SDK/Module/AzureCosmosDBV3/CosmosModelInfo.cs
  29. 6 6
      TEAMModelOS.SDK/Module/AzureCosmosDBV3/CosmosDbQuery.cs
  30. 46 0
      TEAMModelOS.SDK/DI/AzureCosmos/Inner/AzureCosmosUtil.cs
  31. 3 3
      TEAMModelOS.SDK/Module/AzureCosmosDBV3/ID.cs
  32. 6 1
      TEAMModelOS.SDK/Module/AzureCosmosDBV3/IdPk.cs
  33. 28 23
      TEAMModelOS.SDK/Module/AzureCosmosDBV3/SQLHelperParametric.cs
  34. 17 0
      TEAMModelOS.SDK/DI/AzureRedis/AzureRedisExtensions.cs
  35. 47 0
      TEAMModelOS.SDK/DI/AzureRedis/AzureRedisFactory.cs
  36. 22 0
      TEAMModelOS.SDK/DI/AzureRedis/AzureRedisFactoryExtensions.cs
  37. 14 0
      TEAMModelOS.SDK/DI/AzureRedis/AzureRedisFactoryOptions.cs
  38. 105 0
      TEAMModelOS.SDK/DI/AzureServiceBus/AzureServiceBusExtensions.cs
  39. 48 0
      TEAMModelOS.SDK/DI/AzureServiceBus/AzureServiceBusFactory.cs
  40. 22 0
      TEAMModelOS.SDK/DI/AzureServiceBus/AzureServiceBusFactoryExtensions.cs
  41. 13 0
      TEAMModelOS.SDK/DI/AzureServiceBus/AzureServiceBusFactoryOptions.cs
  42. 99 0
      TEAMModelOS.SDK/DI/AzureStorage/AzureStorageBlobExtensions.cs
  43. 350 0
      TEAMModelOS.SDK/DI/AzureStorage/AzureStorageFactory.cs
  44. 22 0
      TEAMModelOS.SDK/DI/AzureStorage/AzureStorageFactoryExtensions.cs
  45. 14 0
      TEAMModelOS.SDK/DI/AzureStorage/AzureStorageFactoryOptions.cs
  46. 516 0
      TEAMModelOS.SDK/DI/AzureStorage/AzureStorageTableExtensions.cs
  47. 7 7
      TEAMModelOS.SDK/Module/AzureBlob/Container/AzureBlobModel.cs
  48. 14 0
      TEAMModelOS.SDK/DI/AzureStorage/Inner/BlobAuth.cs
  49. 2 2
      TEAMModelOS.SDK/Module/AzureBlob/Configuration/BlobSas.cs
  50. 114 0
      TEAMModelOS.SDK/DI/DingDing/DingDing.cs
  51. 154 0
      TEAMModelOS.SDK/DI/SnowflakeID/SnowflakeID.cs
  52. 28 0
      TEAMModelOS.SDK/DI/SnowflakeID/SnowflakeIDExtensions.cs
  53. 20 0
      TEAMModelOS.SDK/DI/SnowflakeID/SnowflakeIDOptions.cs
  54. 4 4
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcRequest/AzureTokenJsonRPCRequest.cs
  55. 2 2
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcRequest/BaseJosnRPCRequest.cs
  56. 3 2
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcRequest/JosnRPCRequest.cs
  57. 15 0
      TEAMModelOS.SDK/Extension/DataResult/JsonRequest/PaginationRequest.cs
  58. 2 2
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/BaseJosnRPCResponse.cs
  59. 3 3
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/DataJosnRPCResponse.cs
  60. 2 2
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/EmptyJosnRPCResponse.cs
  61. 3 3
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/ErrorJosnRPCResponse.cs
  62. 1 1
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/ErrorModel.cs
  63. 1 1
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/JsonRPCResult.cs
  64. 5 5
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/PageJosnRPCResponse.cs
  65. 15 0
      TEAMModelOS.SDK/Extension/DataResult/JsonResponse/PageJsonResult.cs
  66. 28 28
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/JsonRPCResponseBuilder.cs
  67. 20 0
      TEAMModelOS.SDK/Extension/DataResult/JsonResponse/TokenJosnResponse.cs
  68. 4 4
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/TokenJsonRPCResult.cs
  69. 0 15
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcRequest/PaginationJosnRPCRequest.cs
  70. 0 17
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/JosnRPCResponse.cs
  71. 0 15
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/PageJsonRPCResult.cs
  72. 0 20
      TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/TokenJosnRPCResponse.cs
  73. 1 1
      TEAMModelOS.SDK/Extension/DataResult/PageToken/AzurePagination.cs
  74. 1 1
      TEAMModelOS.SDK/Extension/DataResult/PageToken/AzureTableToken.cs
  75. 1 1
      TEAMModelOS.SDK/Extension/DataResult/PageToken/Pagination.cs
  76. 0 12
      TEAMModelOS.SDK/Extension/DataResult/PageToken/PaginationData.cs
  77. 2 2
      TEAMModelOS.SDK/Extension/DataResult/RequestData/AzureTokenRequest.cs
  78. 1 1
      TEAMModelOS.SDK/Extension/DataResult/RequestData/BaseRequest.cs
  79. 2 2
      TEAMModelOS.SDK/Extension/DataResult/RequestData/PaginationRequest.cs
  80. 0 16
      TEAMModelOS.SDK/Extension/DataResult/ResponseData/BaseResponse.cs
  81. 0 14
      TEAMModelOS.SDK/Extension/DataResult/ResponseData/DataResponse.cs
  82. 0 15
      TEAMModelOS.SDK/Extension/DataResult/ResponseData/PageDatasResponse.cs
  83. 0 162
      TEAMModelOS.SDK/Extension/DataResult/ResponseData/ResponseBuilder.cs
  84. 0 16
      TEAMModelOS.SDK/Extension/DataResult/ResponseData/TimeStampResponse.cs
  85. 0 14
      TEAMModelOS.SDK/Extension/DataResult/ResponseData/TokenPageDatasResponse.cs
  86. 22 0
      TEAMModelOS.SDK/Extension/EnumExtensions.cs
  87. 94 0
      TEAMModelOS.SDK/Extension/HttpContextExtensions.cs
  88. 52 0
      TEAMModelOS.SDK/Extension/JsonExtensions.cs
  89. 13 10
      TEAMModelOS.SDK/Extension/MessagePush/Implements/SendCloudService.cs
  90. 94 0
      TEAMModelOS.SDK/Extension/Utils.cs
  91. 1 1
      TEAMModelOS.SDK/Helper/Security/RSACrypt/RSAUtils.cs
  92. 0 12
      TEAMModelOS.SDK/Module/AzureBlob/Configuration/AzureBlobConfig.cs
  93. 0 19
      TEAMModelOS.SDK/Module/AzureBlob/Configuration/AzureBlobOptions.cs
  94. 0 24
      TEAMModelOS.SDK/Module/AzureBlob/Configuration/AzureBlobServiceBuilder.cs
  95. 0 48
      TEAMModelOS.SDK/Module/AzureBlob/Configuration/AzureBlobServiceCollectionExtensions.cs
  96. 0 43
      TEAMModelOS.SDK/Module/AzureBlob/Configuration/BlobClientSingleton.cs
  97. 0 18
      TEAMModelOS.SDK/Module/AzureBlob/Configuration/BlobFileDto.cs
  98. 0 12
      TEAMModelOS.SDK/Module/AzureBlob/Container/FileContainer.cs
  99. 0 11
      TEAMModelOS.SDK/Module/AzureBlob/Container/IBlobContainer.cs
  100. 0 0
      TEAMModelOS.SDK/Module/AzureBlob/Container/ImageContainer.cs

+ 264 - 0
TEAMModelFunction/.gitignore

@@ -0,0 +1,264 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# Azure Functions localsettings file
+local.settings.json
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# DNX
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# TODO: Comment the next line if you want to checkin your web deploy settings
+# but database connection strings (with potential passwords) will be unencrypted
+#*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/packages/repositories.config
+# NuGet v3's project.json files produces more ignoreable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+node_modules/
+orleans.codegen.cs
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush
+.cr/
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc

+ 35 - 0
TEAMModelFunction/MonitorCosmosDB.cs

@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Net.Http;
+using System.Threading.Tasks;
+using Microsoft.Azure.Documents;
+using Microsoft.Azure.WebJobs;
+using Microsoft.Azure.WebJobs.Host;
+using Microsoft.Extensions.Logging;
+
+namespace TEAMModelFunction
+{
+    public class MonitorCosmosDB
+    {
+        private readonly IHttpClientFactory _clientFactory;        
+
+        public MonitorCosmosDB( IHttpClientFactory clientFactory)
+        {
+            _clientFactory = clientFactory;            
+        }
+
+        [FunctionName("School")]
+        public async Task School([CosmosDBTrigger(
+            databaseName: "TEAMModelOS",
+            collectionName: "School",
+            ConnectionStringSetting = "CosmosConnection",
+            LeaseCollectionName = "leases")]IReadOnlyList<Document> input, ILogger log)
+        {           
+                if (input != null && input.Count > 0)
+                {
+                    log.LogInformation("Documents modified " + input.Count);
+                    log.LogInformation("First document Id " + input[0].Id);
+                }           
+        }
+    }
+}

+ 17 - 0
TEAMModelFunction/MonitorServicesBus.cs

@@ -0,0 +1,17 @@
+using System;
+using Microsoft.Azure.WebJobs;
+using Microsoft.Azure.WebJobs.Host;
+using Microsoft.Extensions.Logging;
+
+namespace TEAMModelFunction
+{
+    public static class MonitorServicesBus
+    {
+        [FunctionName("test_queue_activetask")]
+        public static void Run([ServiceBusTrigger("test_queue_activetask", Connection = "ServiceBusConnection")]string myQueueItem, ILogger log)
+        {
+            ///ÖØÊÔ´ÎÊý
+            log.LogInformation($"C# ServiceBus queue trigger function processed message: {myQueueItem}");
+        }
+    }
+}

+ 8 - 0
TEAMModelFunction/Properties/serviceDependencies.json

@@ -0,0 +1,8 @@
+{
+  "dependencies": {
+    "storage1": {
+      "type": "storage",
+      "connectionId": "AzureWebJobsStorage"
+    }
+  }
+}

+ 9 - 0
TEAMModelFunction/Properties/serviceDependencies.local.json

@@ -0,0 +1,9 @@
+{
+  "dependencies": {
+    "storage1": {
+      "resourceId": "/subscriptions/[parameters('subscriptionId')]/resourceGroups/[parameters('resourceGroup')]/providers/Microsoft.Storage/storageAccounts/teammodelstorage",
+      "type": "storage.azure",
+      "connectionId": "AzureWebJobsStorage"
+    }
+  }
+}

+ 19 - 0
TEAMModelFunction/Startup.cs

@@ -0,0 +1,19 @@
+using Microsoft.Azure.Functions.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using System.Text;
+
+[assembly: FunctionsStartup(typeof(TEAMModelFunction.Startup))]
+namespace TEAMModelFunction
+{
+    public class Startup : FunctionsStartup
+    {
+        public override void Configure(IFunctionsHostBuilder builder)
+        {
+            builder.Services.AddHttpClient();            
+        }
+    }
+}

+ 25 - 0
TEAMModelFunction/TEAMModelFunction.csproj

@@ -0,0 +1,25 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <TargetFramework>netcoreapp3.1</TargetFramework>
+    <AzureFunctionsVersion>v3</AzureFunctionsVersion>
+  </PropertyGroup>
+  <ItemGroup>
+    <PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.0.0" />
+    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.CosmosDB" Version="3.0.7" />
+    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.ServiceBus" Version="4.1.2" />
+    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.7" />
+    <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.5.0" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\TEAMModelOS.SDK\TEAMModelOS.SDK.csproj" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Update="host.json">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </None>
+    <None Update="local.settings.json">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
+    </None>
+  </ItemGroup>
+</Project>

+ 11 - 0
TEAMModelFunction/host.json

@@ -0,0 +1,11 @@
+{
+    "version": "2.0",
+    "logging": {
+        "applicationInsights": {
+            "samplingExcludedTypes": "Request",
+            "samplingSettings": {
+                "isEnabled": true
+            }
+        }
+    }
+}

+ 1 - 1
TEAMModelGrpc/Models/ListPid.cs

@@ -3,7 +3,7 @@ using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
-using TEAMModelOS.SDK.Module.AzureCosmosDBV3;
+using TEAMModelOS.SDK.DI;
 
 namespace TEAMModelGrpc.Models
 {

+ 0 - 77
TEAMModelGrpc/Services/BlobSASService.cs

@@ -1,77 +0,0 @@
-using Google.Protobuf.WellKnownTypes;
-using Grpc.Core;
-using Grpc.Extension.Abstract;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using TEAMModelGrpc.Models;
-using TEAMModelOS;
-using TEAMModelOS.SDK.Context.Exception;
-using TEAMModelOS.SDK.Module.AzureBlob.Interfaces;
-
-namespace TEAMModelGrpc.Services
-{
-    public class BlobSASService : IGrpcService
-    {
-
-        private readonly IAzureBlobDBRepository _azureBlobDBRepository;
-
-        public BlobSASService(IAzureBlobDBRepository azureBlobDBRepository)
-        {
-            _azureBlobDBRepository = azureBlobDBRepository;
-        }
-
-        /// <summary>
-        /// 获取bolb共享访问权限
-        /// </summary>
-        /// <param name="empty"></param>
-        /// <param name="context"></param>
-        /// <returns></returns>
-        public async Task<BlobSASDto> GetContainerSasUri(Empty empty, ServerCallContext context) {
-            (string,string, string) aaa = await _azureBlobDBRepository.GetContainerSasUri();
-            BlobSASDto blobSASDto = new BlobSASDto();
-            blobSASDto.Url = aaa.Item1;
-            blobSASDto.Container = aaa.Item2;
-            blobSASDto.SAS = aaa.Item3;
-            return blobSASDto;
-        }
-
-        /// <summary>
-        /// 获取blob共享访问权限 (只读)
-        /// </summary>
-        /// <param name="blob"></param>
-        /// <param name="context"></param>
-        /// <returns></returns>
-        public async Task<BlobSASDto> GetContainerSASRead(BlobSASDto blob, ServerCallContext context)
-        {
-            (string, string) a = BlobUrlString(blob.Url);
-            string ContainerName = a.Item1;
-            string BlobName = a.Item2;
-            bool flg = IsBlobName(BlobName);
-            if (flg)
-            {
-                string SAS = await _azureBlobDBRepository.GetBlobSasUriRead(ContainerName, BlobName);
-                return new BlobSASDto { Url = SAS };
-            }
-            else throw new BizException("文件名错误", ResponseCode.PARAMS_ERROR);
-        }
-
-        private static (string, string) BlobUrlString(string sasUrl)
-        {
-            sasUrl = sasUrl.Substring(8);
-            string[] sasUrls = sasUrl.Split("/");
-            string ContainerName;
-            ContainerName = sasUrls[1].Clone().ToString();
-            string item = sasUrls[0] + "/" + sasUrls[1] + "/";
-            string blob = sasUrl.Replace(item, "");
-            return (ContainerName, blob);
-        }
-
-        public static bool IsBlobName(string BlobName)
-        {
-            return System.Text.RegularExpressions.Regex.IsMatch(BlobName,
-             @"(?!((^(con)$)|^(con)\\..*|(^(prn)$)|^(prn)\\..*|(^(aux)$)|^(aux)\\..*|(^(nul)$)|^(nul)\\..*|(^(com)[1-9]$)|^(com)[1-9]\\..*|(^(lpt)[1-9]$)|^(lpt)[1-9]\\..*)|^\\s+|.*\\s$)(^[^\\\\\\:\\<\\>\\*\\?\\\\\\""\\\\|]{1,255}$)");
-        }
-    }
-}

+ 3 - 3
TEAMModelGrpc/Services/ClassroomService.cs

@@ -7,16 +7,16 @@ using System.Linq;
 using System.Threading.Tasks;
 using TEAMModelGrpc.Models;
 using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
-using TEAMModelOS.SDK.Module.AzureCosmosDBV3;
+using TEAMModelOS.SDK.DI;
 using TEAMModelOS.Service.Models;
 
 namespace TEAMModelGrpc.Services
 {
     public class ClassroomService : IGrpcService
     {
-        public readonly IAzureCosmosDBV3Repository cosmosrepository;
+        public readonly AzureCosmosFactory cosmosrepository;
 
-        public ClassroomService(IAzureCosmosDBV3Repository cosmosrepository)
+        public ClassroomService(AzureCosmosFactory cosmosrepository)
         {
             this.cosmosrepository = cosmosrepository;
         }

+ 3 - 3
TEAMModelGrpc/Services/ClassroomStudentService.cs

@@ -7,15 +7,15 @@ using System.Linq;
 using System.Threading.Tasks;
 using TEAMModelGrpc.Models;
 using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
-using TEAMModelOS.SDK.Module.AzureCosmosDBV3;
+using TEAMModelOS.SDK.DI;
 using TEAMModelOS.Service.Models;
 
 namespace TEAMModelGrpc.Services
 {
     public class ClassStudentService : IGrpcService
     {
-        private IAzureCosmosDBV3Repository _cosmos;
-        public ClassStudentService(IAzureCosmosDBV3Repository cosmos)
+        private AzureCosmosFactory _cosmos;
+        public ClassStudentService(AzureCosmosFactory cosmos)
         {
             _cosmos = cosmos;
         }

+ 3 - 3
TEAMModelGrpc/Services/CourseService.cs

@@ -6,16 +6,16 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
 using TEAMModelGrpc.Models;
-using TEAMModelOS.SDK.Module.AzureCosmosDBV3;
+using TEAMModelOS.SDK.DI;
 using TEAMModelOS.Service.Models;
 
 namespace TEAMModelGrpc.Services
 {
     public class CourseService : IGrpcService
     {
-        public IAzureCosmosDBV3Repository _cosmos;
+        public AzureCosmosFactory _cosmos;
 
-        public CourseService(IAzureCosmosDBV3Repository cosmosDBV3Repository)
+        public CourseService(AzureCosmosFactory cosmosDBV3Repository)
         {
             this._cosmos = cosmosDBV3Repository;
         }

+ 3 - 3
TEAMModelGrpc/Services/HomeWorkService.cs

@@ -9,16 +9,16 @@ using TEAMModelOS;
 using TEAMModelOS.Models;
 using TEAMModelOS.SDK.Context.Exception;
 using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
-using TEAMModelOS.SDK.Module.AzureCosmosDBV3;
+using TEAMModelOS.SDK.DI;
 using TEAMModelOS.Service.Models;
 
 namespace TEAMModelGrpc.Services
 {
     public class HomeWorkService : IGrpcService
     {
-        private readonly IAzureCosmosDBV3Repository _cosmos;
+        private readonly AzureCosmosFactory _cosmos;
 
-        public HomeWorkService(IAzureCosmosDBV3Repository cosmos)
+        public HomeWorkService(AzureCosmosFactory cosmos)
         {
             _cosmos = cosmos;
         }

+ 0 - 93
TEAMModelGrpc/Services/KnowledgeService.cs

@@ -1,93 +0,0 @@
-using Google.Protobuf;
-using Grpc.Core;
-using Grpc.Extension.Abstract;
-using Microsoft.AspNetCore.Authorization;
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using TEAMModelGrpc.Models;
-using TEAMModelOS.SDK.Helper.Common.JsonHelper;
-using TEAMModelOS.SDK.Module.AzureCosmosDBV3;
-using TEAMModelOS.Service.Models;
-using TEAMModelOS.Service.Services.Interface;
-
-namespace TEAMModelGrpc.Services
-{
- 
-    public class KnowledgeService : IGrpcService
-    {
-        private IAzureCosmosDBV3Repository cosmosDBV3Repository;
-        private IKnowledgeService knowledgeService;
-
-        public KnowledgeService(IAzureCosmosDBV3Repository cosmosDBV3Repository, IKnowledgeService knowledgeService)
-        {
-            this.cosmosDBV3Repository = cosmosDBV3Repository;
-            this.knowledgeService = knowledgeService;
-        }
-
-
-        /// <summary>
-        /// 查询知识点
-        /// </summary>
-        /// <param name="request"></param>
-        /// <param name="responseStream"></param>
-        /// <param name="context"></param>
-        /// <returns></returns>
-        [Authorize]
-        public async Task FinKnowledge(Dict request, IServerStreamWriter<Knowledge> responseStream, ServerCallContext context)
-        {
-            Dictionary<string, object> keyValuePairs = new Dictionary<string, object>();
-            keyValuePairs = request.ToDict();
-            List<Knowledge> knowledges = await cosmosDBV3Repository.FindByDict<Knowledge>(keyValuePairs);
-            knowledges.ForEach(x =>
-            {
-                responseStream.WriteAsync(x);
-            });
-        }
-
-
-        /// <summary>
-        /// 保存知识点
-        /// </summary>
-        /// <param name="requestStream"></param>
-        /// <param name="responseStream"></param>
-        /// <param name="context"></param>
-        /// <returns></returns>
-        [Authorize]
-        public async Task SaveKnowledge(IAsyncStreamReader<Knowledge> requestStream, IServerStreamWriter<Knowledge> responseStream, ServerCallContext context)
-        {
-            //Dictionary<string, object> keyValuePairs = new Dictionary<string, object>();
-            //keyValuePairs = request.ToDict();
-            List<Knowledge> knowledges = new List<Knowledge>();
-            await foreach (var message in requestStream.ReadAllAsync())
-            {
-                knowledges.Add(message);
-            }
-
-            await knowledgeService.SaveOrUpdateKnowledge(knowledges);
-
-            knowledges.ForEach(x =>
-            {
-                responseStream.WriteAsync(x);
-            });
-        }
-
-
-        /// <summary>
-        /// 删除知识点
-        /// </summary>
-        /// <param name="listPid"></param>
-        /// <param name="context"></param>
-        /// <returns></returns>
-        [Authorize]
-        public async Task<ListPid> DeleteKnowledge(ListPid listPid, ServerCallContext context)
-        {
-            List<IdPk> idPks = await knowledgeService.DeleteKnowledge(listPid.idPks);//await cosmosDBV3Repository.DeleteAll<Knowledge>(listPid.idPks);
-            listPid.idPks = idPks;
-            return listPid;
-        }
-
-    }
-}

+ 0 - 124
TEAMModelGrpc/Services/SyllabusService.cs

@@ -1,124 +0,0 @@
-using Grpc.Core;
-using Grpc.Extension.Abstract;
-using Microsoft.AspNetCore.Authorization;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using TEAMModelGrpc.Models;
-using TEAMModelOS.SDK.Helper.Common.JsonHelper;
-using TEAMModelOS.SDK.Module.AzureCosmosDBV3;
-using TEAMModelOS.Service.Models;
-using TEAMModelOS.Service.Services.Interface;
-
-namespace TEAMModelGrpc.Services
-{
-    /// <summary>
-    /// 课纲业务
-    /// </summary>
-    public class SyllabusService : IGrpcService
-    {
-        private ISyllabusService syllabusService;
-        private IAzureCosmosDBV3Repository cosmosDBV3Repository;
-        /// <summary>
-        /// 构造函数
-        /// </summary>
-        /// <param name="syllabusService"></param>
-        /// <param name="cosmosDBV3Repository"></param>
-        public SyllabusService(ISyllabusService syllabusService, IAzureCosmosDBV3Repository cosmosDBV3Repository)
-        {
-            this.syllabusService = syllabusService;
-            this.cosmosDBV3Repository = cosmosDBV3Repository;
-        }
-
-
-        /// <summary>
-        /// 查找课纲 
-        /// </summary>
-        /// <param name="request"></param>
-        /// <param name="responseStream"></param>
-        /// <param name="context"></param>
-        /// <returns></returns>
-        [Authorize]
-        public async Task FindSyllabusTree(Dict request, IServerStreamWriter<SyllabusTreeDto> responseStream, ServerCallContext context) 
-        {
-            Dictionary<string, object> keyValuePairs = new Dictionary<string, object>();
-            keyValuePairs = request.ToDict();
-            List<SyllabusTree> knowledges = await syllabusService.Find(keyValuePairs);
-            List<SyllabusTreeDto> list = knowledges.ToJson().FromJson<List<SyllabusTreeDto>>();
-
-            list.ForEach(x =>
-            {
-                responseStream.WriteAsync(x);
-            });
-        }
-
-        /// <summary>
-        /// 按节点新增课纲
-        /// </summary>
-        /// <param name="requestStream"></param>
-        /// <param name="context"></param>
-        /// <returns></returns>
-        public async Task<Response> SaveOrUpdateAsNodes(IAsyncStreamReader<SyllabusNode> requestStream,  ServerCallContext context) 
-        {
-
-            List<SyllabusNode> syllabusNodes = new List<SyllabusNode>();
-            await foreach (SyllabusNode syllabusNode in requestStream.ReadAllAsync()) 
-            {
-                syllabusNodes.Add(syllabusNode);
-            }
-
-            await syllabusService.SaveOrUpdateAsNodes(syllabusNodes);
-            Response response = new Response();
-            return response.Success();
-        }
-
-        /// <summary>
-        ///  按树形新增课纲结构
-        /// </summary>
-        /// <param name="requestStream"></param>
-        /// <param name="responseStream"></param>
-        /// <param name="context"></param>
-        /// <returns></returns>
-        public async Task SaveOrUpdateAsTree(IAsyncStreamReader<SyllabusTreeDto> requestStream, IServerStreamWriter<SyllabusTreeDto> responseStream, ServerCallContext context)
-        {
-
-            List<SyllabusTree> syllabusTrees = new List<SyllabusTree>();
-            List<SyllabusTreeDto> syllabusTreeDtos = new List<SyllabusTreeDto>();
-            await foreach (SyllabusTreeDto syllabusNode in requestStream.ReadAllAsync())
-            {
-                syllabusTreeDtos.Add(syllabusNode);
-                SyllabusTree syllabusTree = syllabusNode.ToJson().FromJson<SyllabusTree>();
-                syllabusTrees.Add(syllabusTree);
-            }
-            await syllabusService.SaveOrUpdateAsTree(syllabusTrees);
-
-            syllabusTreeDtos.ForEach(x => {
-                responseStream.WriteAsync(x);
-            });
-        }
-
-
-        /// <summary>
-        /// 删除课纲
-        /// </summary>
-        /// <param name="request"></param>
-        /// <param name="responseStream"></param>
-        /// <param name="context"></param>
-        /// <returns></returns>
-        [Authorize]
-        public async Task DeleteSyllabus(Dict request, IServerStreamWriter<SyllabusTreeDto> responseStream, ServerCallContext context)
-        {
-            Dictionary<string, object> keyValuePairs = new Dictionary<string, object>();
-            keyValuePairs = request.ToDict();
-            List<Syllabus> syllabuses = await syllabusService.DeleteSyllabus(keyValuePairs);//await cosmosDBV3Repository.DeleteAll<Knowledge>(listPid.idPks);
-            List<SyllabusTreeDto> syllabusTreeDtos = syllabuses.ToJson().FromJson<List<SyllabusTreeDto>>();
-
-            syllabusTreeDtos.ForEach(x => { 
-                responseStream.WriteAsync(x);
-            });
-        }
-
-
-    }
-}

+ 0 - 82
TEAMModelGrpc/Services/VolumeService.cs

@@ -1,82 +0,0 @@
-using Grpc.Core;
-using Grpc.Extension.Abstract;
-using Microsoft.AspNetCore.Authorization;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using TEAMModelGrpc.Models;
-using TEAMModelOS.SDK.Module.AzureCosmosDBV3;
-using TEAMModelOS.Service.Models;
-using TEAMModelOS.Service.Services.Interface;
-
-namespace TEAMModelGrpc.Services
-{
-    public class VolumeService :IGrpcService
-    {
-        private readonly IAzureCosmosDBV3Repository azureCosmosDBRepository;
-        private IVolumeService volumeService;
-
-        public VolumeService(IAzureCosmosDBV3Repository azureCosmosDBRepository, IVolumeService volumeService)
-        {
-            this.azureCosmosDBRepository = azureCosmosDBRepository;
-            this.volumeService = volumeService;
-        }
-
-        /// <summary>
-        /// 保存册别
-        /// </summary>
-        /// <param name="requestStream"></param>
-        /// <param name="responseStream"></param>
-        /// <param name="context"></param>
-        /// <returns></returns>
-        [Authorize]
-        public async Task SaveOrUpdateVolume(IAsyncStreamReader<Volume> requestStream, IServerStreamWriter<Volume> responseStream, ServerCallContext context) {
-
-            List<Volume> volumes = new List<Volume>();
-            await foreach (Volume syllabusNode in requestStream.ReadAllAsync())
-            {
-                List<Volume> volume = await volumeService.SaveOrUpdateVolume(syllabusNode);
-                volumes.AddRange(volume);
-            }
-            volumes.ForEach(x => {
-                responseStream.WriteAsync(x);
-            });
-        }
-
-        /// <summary>
-        /// 查询册别
-        /// </summary>
-        /// <param name="request"></param>
-        /// <param name="responseStream"></param>
-        /// <param name="context"></param>
-        /// <returns></returns>
-        [Authorize]
-        public async Task FindVolume(Dict request, IServerStreamWriter<Volume> responseStream, ServerCallContext context) {
-
-            Dictionary<string, object> dict = request.ToDict();
-
-            List<Volume> syllabusVolumes = await azureCosmosDBRepository.FindByDict<Volume>(dict);
-
-            syllabusVolumes.ForEach(x => { 
-                responseStream.WriteAsync(x);
-            });
-        }
-
-
-        /// <summary>
-        ///  删除册别
-        /// </summary>
-        /// <param name="listPid"></param>
-        /// <param name="context"></param>
-        /// <returns></returns>
-        [Authorize]
-        public async Task<ListPid> Delete(ListPid listPid, ServerCallContext context)
-        {
-            List<IdPk> idPks = await azureCosmosDBRepository.DeleteAll<Volume>(listPid.idPks);
-            listPid.idPks = idPks;
-            return listPid;
-        }
-
-    }
-}

+ 9 - 14
TEAMModelGrpc/Startup.cs

@@ -1,4 +1,4 @@
-using System;
+using System;
 using System.Collections.Generic;
 using System.IdentityModel.Tokens.Jwt;
 using System.Linq;
@@ -17,12 +17,7 @@ using Microsoft.Extensions.Primitives;
 using Microsoft.IdentityModel.Tokens;
 using TEAMModelGrpc.Services;
 using TEAMModelOS.SDK.Context.Configuration;
-using TEAMModelOS.SDK.Extension.JwtAuth;
-using TEAMModelOS.SDK.Module.AzureBlob.Configuration;
-using TEAMModelOS.SDK.Module.AzureCosmosDB.Configuration;
-using TEAMModelOS.SDK.Module.AzureCosmosDBV3;
-using TEAMModelOS.SDK.Module.AzureTable.Implements;
-using TEAMModelOS.SDK.Module.AzureTable.Interfaces;
+using TEAMModelOS.SDK.DI;
 using Microsoft.Extensions.Diagnostics.HealthChecks;
 
 namespace TEAMModelGrpc
@@ -76,12 +71,12 @@ namespace TEAMModelGrpc
                 });
 
             // Table配置
-            services.AddScoped<IAzureTableDBRepository, AzureTableDBRepository>();
+            //services.AddScoped<IAzureTableDBRepository, AzureTableDBRepository>();
             //使用Blob配置
-            services.AddAzureBlobStorage().AddConnection(_conf.GetSection("Azure:Blob").Get<AzureBlobOptions>());
+            //services.AddAzureBlobStorage().AddConnection(_conf.GetSection("Azure:Blob").Get<AzureBlobOptions>());
             //使用CosmosDB
-            services.AddAzureCosmosDBV3().AddCosmosDBV3Connection(_conf.GetSection("Azure:CosmosDB").Get<AzureCosmosDBOptions>())
-                .AddCosmosSerializer(new SystemTextJsonCosmosSerializer(new JsonSerializerOptions() { IgnoreNullValues = true }));
+            //services.AddAzureCosmosDBV3().AddCosmosDBV3Connection(_conf.GetSection("Azure:CosmosDB").Get<AzureCosmosDBOptions>())
+            //    .AddCosmosSerializer(new SystemTextJsonCosmosSerializer(new JsonSerializerOptions() { IgnoreNullValues = true }));
  
             //注入CSRedis
             var csredis = new CSRedis.CSRedisClient(_conf.GetSection("Azure:Redis:ConnectionString").Get<string>());
@@ -96,7 +91,7 @@ namespace TEAMModelGrpc
         }
 
         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
-        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IAzureCosmosDBV3Repository cosmosDBV3Repository)
+        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, AzureCosmosFactory cosmosDBV3Repository)
         {
             if (env.IsDevelopment())
             {
@@ -112,7 +107,7 @@ namespace TEAMModelGrpc
 
             app.UseEndpoints(endpoints =>
             {
-                endpoints.MapGrpcService<KnowledgeService>();
+                endpoints.MapGrpcService<HomeWorkService>();
                 endpoints.MapGrpcHealthChecksService();
                 endpoints.MapGet("/generateJwtToken", context =>
                 {
@@ -127,7 +122,7 @@ namespace TEAMModelGrpc
             //CodeFirst的Grpc(会自动扫描TStartup所在程序集下的IGrpcSerivce)
 
 
-            app.UseGrpcExtensions<TEAMModelGrpc.Services.KnowledgeService>(options =>
+            app.UseGrpcExtensions<TEAMModelGrpc.Services.HomeWorkService>(options =>
             {
                 //CodeFirst配制
                 options.GlobalPackage = "TMDGrpc";

+ 0 - 115
TEAMModelGrpc/TEAMModelOS.GRPC.xml

@@ -206,22 +206,6 @@
             数据状态
             </summary>
         </member>
-        <member name="M:TEAMModelGrpc.Services.BlobSASService.GetContainerSasUri(Google.Protobuf.WellKnownTypes.Empty,Grpc.Core.ServerCallContext)">
-            <summary>
-            获取bolb共享访问权限
-            </summary>
-            <param name="empty"></param>
-            <param name="context"></param>
-            <returns></returns>
-        </member>
-        <member name="M:TEAMModelGrpc.Services.BlobSASService.GetContainerSASRead(TEAMModelGrpc.Models.BlobSASDto,Grpc.Core.ServerCallContext)">
-            <summary>
-            获取blob共享访问权限 (只读)
-            </summary>
-            <param name="blob"></param>
-            <param name="context"></param>
-            <returns></returns>
-        </member>
         <member name="M:TEAMModelGrpc.Services.ClassroomService.SaveOrUpdateVolume(Grpc.Core.IAsyncStreamReader{TEAMModelOS.Service.Models.Classroom},Grpc.Core.IServerStreamWriter{TEAMModelOS.Service.Models.Classroom},Grpc.Core.ServerCallContext)">
             <summary>
             保存教室
@@ -317,105 +301,6 @@
             <param name="context"></param>
             <returns></returns>
         </member>
-        <member name="M:TEAMModelGrpc.Services.KnowledgeService.FinKnowledge(TEAMModelGrpc.Models.Dict,Grpc.Core.IServerStreamWriter{TEAMModelOS.Service.Models.Knowledge},Grpc.Core.ServerCallContext)">
-            <summary>
-            查询知识点
-            </summary>
-            <param name="request"></param>
-            <param name="responseStream"></param>
-            <param name="context"></param>
-            <returns></returns>
-        </member>
-        <member name="M:TEAMModelGrpc.Services.KnowledgeService.SaveKnowledge(Grpc.Core.IAsyncStreamReader{TEAMModelOS.Service.Models.Knowledge},Grpc.Core.IServerStreamWriter{TEAMModelOS.Service.Models.Knowledge},Grpc.Core.ServerCallContext)">
-            <summary>
-            保存知识点
-            </summary>
-            <param name="requestStream"></param>
-            <param name="responseStream"></param>
-            <param name="context"></param>
-            <returns></returns>
-        </member>
-        <member name="M:TEAMModelGrpc.Services.KnowledgeService.DeleteKnowledge(TEAMModelGrpc.Models.ListPid,Grpc.Core.ServerCallContext)">
-            <summary>
-            删除知识点
-            </summary>
-            <param name="listPid"></param>
-            <param name="context"></param>
-            <returns></returns>
-        </member>
-        <member name="T:TEAMModelGrpc.Services.SyllabusService">
-            <summary>
-            课纲业务
-            </summary>
-        </member>
-        <member name="M:TEAMModelGrpc.Services.SyllabusService.#ctor(TEAMModelOS.Service.Services.Interface.ISyllabusService,TEAMModelOS.SDK.Module.AzureCosmosDBV3.IAzureCosmosDBV3Repository)">
-            <summary>
-            构造函数
-            </summary>
-            <param name="syllabusService"></param>
-            <param name="cosmosDBV3Repository"></param>
-        </member>
-        <member name="M:TEAMModelGrpc.Services.SyllabusService.FindSyllabusTree(TEAMModelGrpc.Models.Dict,Grpc.Core.IServerStreamWriter{TEAMModelGrpc.Models.SyllabusTreeDto},Grpc.Core.ServerCallContext)">
-            <summary>
-            查找课纲 
-            </summary>
-            <param name="request"></param>
-            <param name="responseStream"></param>
-            <param name="context"></param>
-            <returns></returns>
-        </member>
-        <member name="M:TEAMModelGrpc.Services.SyllabusService.SaveOrUpdateAsNodes(Grpc.Core.IAsyncStreamReader{TEAMModelOS.Service.Models.SyllabusNode},Grpc.Core.ServerCallContext)">
-            <summary>
-            按节点新增课纲
-            </summary>
-            <param name="requestStream"></param>
-            <param name="context"></param>
-            <returns></returns>
-        </member>
-        <member name="M:TEAMModelGrpc.Services.SyllabusService.SaveOrUpdateAsTree(Grpc.Core.IAsyncStreamReader{TEAMModelGrpc.Models.SyllabusTreeDto},Grpc.Core.IServerStreamWriter{TEAMModelGrpc.Models.SyllabusTreeDto},Grpc.Core.ServerCallContext)">
-            <summary>
-             按树形新增课纲结构
-            </summary>
-            <param name="requestStream"></param>
-            <param name="responseStream"></param>
-            <param name="context"></param>
-            <returns></returns>
-        </member>
-        <member name="M:TEAMModelGrpc.Services.SyllabusService.DeleteSyllabus(TEAMModelGrpc.Models.Dict,Grpc.Core.IServerStreamWriter{TEAMModelGrpc.Models.SyllabusTreeDto},Grpc.Core.ServerCallContext)">
-            <summary>
-            删除课纲
-            </summary>
-            <param name="request"></param>
-            <param name="responseStream"></param>
-            <param name="context"></param>
-            <returns></returns>
-        </member>
-        <member name="M:TEAMModelGrpc.Services.VolumeService.SaveOrUpdateVolume(Grpc.Core.IAsyncStreamReader{TEAMModelOS.Service.Models.Volume},Grpc.Core.IServerStreamWriter{TEAMModelOS.Service.Models.Volume},Grpc.Core.ServerCallContext)">
-            <summary>
-            保存册别
-            </summary>
-            <param name="requestStream"></param>
-            <param name="responseStream"></param>
-            <param name="context"></param>
-            <returns></returns>
-        </member>
-        <member name="M:TEAMModelGrpc.Services.VolumeService.FindVolume(TEAMModelGrpc.Models.Dict,Grpc.Core.IServerStreamWriter{TEAMModelOS.Service.Models.Volume},Grpc.Core.ServerCallContext)">
-            <summary>
-            查询册别
-            </summary>
-            <param name="request"></param>
-            <param name="responseStream"></param>
-            <param name="context"></param>
-            <returns></returns>
-        </member>
-        <member name="M:TEAMModelGrpc.Services.VolumeService.Delete(TEAMModelGrpc.Models.ListPid,Grpc.Core.ServerCallContext)">
-            <summary>
-             删除册别
-            </summary>
-            <param name="listPid"></param>
-            <param name="context"></param>
-            <returns></returns>
-        </member>
         <member name="T:TEAMModelGrpc.GreetReflection">
             <summary>Holder for reflection information generated from Protos/greet.proto</summary>
         </member>

+ 1 - 0
TEAMModelOS.SDK/Context/Attributes/Azure/CosmosDBAttribute.cs

@@ -11,5 +11,6 @@ namespace TEAMModelOS.SDK.Context.Attributes.Azure
         public string Name { get; set; }
         public bool Cache { get; set; } = false;
         public bool Monitor { get; set; } = false;
+        public string Database { get; set; } = "TEAMModelOS";
     }
 }

+ 61 - 0
TEAMModelOS.SDK/Context/Configuration/Option.cs

@@ -0,0 +1,61 @@
+using Microsoft.AspNetCore.Authentication.OAuth;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Primitives;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace TEAMModelOS.Models
+{
+    public class Option
+    {
+        public Option()
+        {
+        }
+
+        public string Location { get; set; }
+        public string LocationNum { get; set; }  
+        public string BlobDomain { get; set; }
+        public string HostName { get; set; }
+        public IList<string> AllowedHosts { get; }
+        public IList<StringSegment> AllowedRedirects
+        {
+            get
+            {
+                var allowedRedirects = new List<StringSegment>();
+                if (AllowedHosts?.Count > 0 && !TryProcessHosts(AllowedHosts, allowedRedirects))
+                {
+                    return allowedRedirects;
+                }
+                return allowedRedirects;
+            }
+        }
+        public string JwtSecretKey { get; set; }
+        public string Authority { get; set; }
+        public string Audience { get; set; }
+        public string OSFunction { get; set; }
+
+
+
+        private bool TryProcessHosts(IEnumerable<string> incoming, IList<StringSegment> results)
+        {
+            foreach (var entry in incoming)
+            {
+                // Punycode. Http.Sys requires you to register Unicode hosts, but the headers contain punycode.
+                var host = new HostString(entry).ToUriComponent();
+                if (IsTopLevelWildcard(host)) continue;
+                if (!results.Contains(host, StringSegmentComparer.OrdinalIgnoreCase)) results.Add(host);
+            }
+            return true;
+        }
+
+        private bool IsTopLevelWildcard(string host)
+        {
+            return (string.Equals("*", host, StringComparison.Ordinal) // HttpSys wildcard
+                           || string.Equals("[::]", host, StringComparison.Ordinal) // Kestrel wildcard, IPv6 Any
+                           || string.Equals("0.0.0.0", host, StringComparison.Ordinal)); // IPv4 Any
+        }
+
+    }  
+}

+ 5 - 5
TEAMModelOS.SDK/Context/Filters/HttpGlobalExceptionInvoke.cs

@@ -1,4 +1,4 @@
-
+
 using Microsoft.AspNetCore.Http;
 using System;
 using System.Threading.Tasks;
@@ -42,18 +42,18 @@ namespace TEAMModelOS.SDK.Context.Filter
                     bizCode = ((BizException)ex).code;
                     if (bizCode == 401 || bizCode == 404 || bizCode == 502 || bizCode == 403)
                     {
-                        context.Response.StatusCode = bizCode;
+                        //context.Response.StatusCode = bizCode;
                     }
                     else
                     {
-                        context.Response.StatusCode = 200;
+                      //  context.Response.StatusCode = 200;
                     }
                     // context.Response.StatusCode = ((BizException)ex).code;
                 }
                 //未知异常
                 else
                 {
-                    context.Response.StatusCode = 500;
+                    //context.Response.StatusCode = 500;
                     //LogHelper.SetLog(LogLevel.Error, ex);
                 }
                 await HandleExceptionAsync(context, bizCode, ex.Message, ex.StackTrace);
@@ -105,7 +105,7 @@ namespace TEAMModelOS.SDK.Context.Filter
         {
             if (context.Response.StatusCode == 500)
             {
-                context.Response.StatusCode = 200;
+               // context.Response.StatusCode = 200;
             }
             var data = new ErrorResponse<string>(bizCode, msg, devmsg);
             context.Response.ContentType = Constants.CONTENT_TYPE_JSON;

+ 743 - 0
TEAMModelOS.SDK/DI/AzureCosmos/AzureCosmosExtensions.cs

@@ -0,0 +1,743 @@
+using Microsoft.Azure.Cosmos.Table;
+using Microsoft.Azure.Cosmos.Table.Queryable;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Linq;
+using Azure;
+using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
+using System.IO;
+using TEAMModelOS.SDK.DI;
+using System.Diagnostics;
+using Azure.Cosmos;
+using System.Text.Json;
+using System.Net;
+using TEAMModelOS.SDK.Context.Exception;
+using System.Linq.Expressions;
+using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
+using TEAMModelOS.SDK.Helper.Common.LogHelper;
+using TEAMModelOS.SDK.Helper.Common.JsonHelper;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public static class AzureCosmosExtensions
+    {
+        /// <summary>
+        /// 缓存前缀
+        /// </summary>
+        private const string CacheCosmosPrefix = "cosmos:";
+        /// <summary>
+        /// ttl时长 1秒
+        /// </summary>
+        private const int ttl = 1;
+        /// <summary>
+        /// 分页大小
+        /// </summary>
+        private const int pageSize = 200;
+        /// <summary>
+        /// 超时时间
+        /// </summary>
+        private const int timeoutSeconds = 86400;
+        public static int RU(this Response response)
+        {
+            try
+            {
+                response.Headers.TryGetValue("x-ms-request-charge", out var value);
+                var ru = Convert.ToInt32(value);
+                return ru;
+            }
+            catch (Exception)
+            {
+                return 0;
+            }
+        }
+        public static async Task<T> FindByIdPk<T>(this AzureCosmosFactory azureCosmosFactory, string id, string pk) where T : ID
+        {
+            AzureCosmosModel container = azureCosmosFactory.GetCosmosModel(typeof(T).Name);
+            try
+            {
+                ItemResponse<T> response = await container.container.ReadItemAsync<T>(id: id, partitionKey: new PartitionKey(pk));
+                return response.Value;
+            }
+            catch (Exception x){
+                return default(T);
+            }
+        }
+        public static async Task<List<T>> FindByIds<T>(this AzureCosmosFactory azureCosmosFactory, List<string> ids) where T : ID
+        {
+            AzureCosmosModel container = azureCosmosFactory.GetCosmosModel(typeof(T).Name);
+            if (container.cache && RedisHelper.Instance != null)
+            {
+                List<T> list = new List<T>();
+                List<string> NotIn = new List<string>();
+                foreach (string id in ids)
+                {
+                    if (!await RedisHelper.HExistsAsync(CacheCosmosPrefix + container.container.Id, id))
+                    {
+                        NotIn.Add(id);
+                    }
+                    else
+                    {
+                        list.Add(await RedisHelper.HGetAsync<T>(CacheCosmosPrefix + container.container.Id, id));
+                    }
+                }
+                if (NotIn.IsNotEmpty())
+                {
+                    List<T> noInList = await FindByDict<T>(azureCosmosFactory, new Dictionary<string, object> { { "id", NotIn.ToArray() } });
+                    noInList.ForEach(x => { RedisHelper.HSet(CacheCosmosPrefix + container.container.Id, x.id, x); RedisHelper.Expire(CacheCosmosPrefix + container.container.Id, timeoutSeconds); });
+                    list.AddRange(noInList);
+                }
+                return list;
+            }
+            else
+            {
+                return await FindByDict<T>(azureCosmosFactory, new Dictionary<string, object> { { "id", ids.ToArray() } });
+            }
+        }
+        public static async Task<T> Save<T>(this AzureCosmosFactory azureCosmosFactory, T entity) where T : ID
+        {
+
+            AzureCosmosModel container = azureCosmosFactory.GetCosmosModel(typeof(T).Name);
+            entity.pk = container.type.Name;
+            entity.ttl = -1;
+            ItemResponse<T> response = await container.container.CreateItemAsync<T>(entity);
+            if (container.cache && RedisHelper.Instance != null)
+            {
+                if (!RedisHelper.Exists(CacheCosmosPrefix + container.container.Id))
+                {
+                    await RedisHelper.HSetAsync(CacheCosmosPrefix + container.container.Id, entity.id, entity);
+                }
+                else
+                {
+                    await RedisHelper.HSetAsync(CacheCosmosPrefix + container.container.Id, entity.id, entity);
+                    await RedisHelper.ExpireAsync(CacheCosmosPrefix + container.container.Id, timeoutSeconds);
+                }
+            }
+            return response.Value;
+        }
+        public static async Task<List<T>> SaveAll<T>(this AzureCosmosFactory azureCosmosFactory, List<T> enyites) where T : ID
+        {
+            Type type = typeof(T);
+            int pages = (int)Math.Ceiling((double)enyites.Count / pageSize);
+            AzureCosmosModel container = azureCosmosFactory.GetCosmosModel(type.Name);
+            bool flag = false;
+            if (RedisHelper.Exists(CacheCosmosPrefix + container.container.Id))
+            {
+                flag = true;
+            }
+            string partitionKey =AzureCosmosUtil.GetPartitionKey (type);
+           
+            Stopwatch stopwatch = Stopwatch.StartNew();
+            for (int i = 0; i < pages; i++)
+            {
+                List<T> lists = enyites.Skip((i) * pageSize).Take(pageSize).ToList();
+                List<KeyValuePair<PartitionKey, Stream>> itemsToInsert = new List<KeyValuePair<PartitionKey, Stream>>();
+                lists.ForEach(async x =>
+                {
+                    x.pk = type.Name;
+                    x.ttl = -1;
+                    MemoryStream stream = new MemoryStream();
+                    await JsonSerializer.SerializeAsync(stream, x, new JsonSerializerOptions { IgnoreNullValues = true });
+                    object o = type.GetProperty(partitionKey).GetValue(x, null);
+                    KeyValuePair<PartitionKey, Stream> keyValue = new KeyValuePair<PartitionKey, Stream>(new PartitionKey(o.ToString()), stream);
+                    itemsToInsert.Add(keyValue);
+                });
+                List<Task> tasks = new List<Task>(lists.Count);
+                itemsToInsert.ForEach(item =>
+                {
+                    tasks.Add(container.container.CreateItemStreamAsync(item.Value, item.Key)
+                        .ContinueWith((Task<Response> task) =>
+                        {
+                            using (Response response = task.Result)
+                            {
+                                //if (!response.IsSuccessStatusCode)
+                                //{
+                                //}
+                            }
+                        }
+                        ));
+                });
+                await Task.WhenAll(tasks);
+                if (container.cache && RedisHelper.Instance != null)
+                {
+                    lists.ForEach(async x => {
+                        await RedisHelper.HSetAsync(CacheCosmosPrefix + container.container.Id, x.id, x);
+                    });
+                }
+            }
+            if (container.cache && RedisHelper.Instance != null && !flag)
+            {
+                await RedisHelper.ExpireAsync(CacheCosmosPrefix + container.container.Id, timeoutSeconds);
+            }
+            stopwatch.Stop();
+            return enyites;
+        }
+        public static async Task<T> SaveOrUpdate<T>(this AzureCosmosFactory azureCosmosFactory, T entity) where T : ID
+        {
+            AzureCosmosModel container = azureCosmosFactory.GetCosmosModel(typeof(T).Name);
+            entity.pk = container.type.Name;
+            entity.ttl = -1;
+            ItemResponse<T> response = await container.container.UpsertItemAsync(item: entity);
+            if (container.cache && RedisHelper.Instance != null)
+            {
+                if (!RedisHelper.Exists(CacheCosmosPrefix + container.container.Id))
+                {
+                    await RedisHelper.HSetAsync(CacheCosmosPrefix + container.container.Id, entity.id, entity);
+                }
+                else
+                {
+                    await RedisHelper.HSetAsync(CacheCosmosPrefix + container.container.Id, entity.id, entity);
+                    await RedisHelper.ExpireAsync(CacheCosmosPrefix + container.container.Id, timeoutSeconds);
+                }
+            }
+            return response.Value;
+        }
+        public static async Task<List<T>> SaveOrUpdateAll<T>(this AzureCosmosFactory azureCosmosFactory, List<T> enyites) where T : ID
+        {
+            Type type = typeof(T);
+            int pages = (int)Math.Ceiling((double)enyites.Count / pageSize);
+            AzureCosmosModel container = azureCosmosFactory.GetCosmosModel(type.Name);
+            bool flag = false;
+            if (RedisHelper.Exists(CacheCosmosPrefix + container.container.Id))
+            {
+                flag = true;
+            }
+            
+            string partitionKey = AzureCosmosUtil.GetPartitionKey(type);
+            
+            Stopwatch stopwatch = Stopwatch.StartNew();
+            for (int i = 0; i < pages; i++)
+            {
+                List<T> lists = enyites.Skip((i) * pageSize).Take(pageSize).ToList();
+                List<KeyValuePair<PartitionKey, Stream>> itemsToInsert = new List<KeyValuePair<PartitionKey, Stream>>();
+                lists.ForEach(async x =>
+                {
+                    x.pk = type.Name;
+                    x.ttl = -1;
+                    MemoryStream stream = new MemoryStream();
+                    await JsonSerializer.SerializeAsync(stream, x, new JsonSerializerOptions { IgnoreNullValues = true });
+                    object o = type.GetProperty(partitionKey).GetValue(x, null);
+                    KeyValuePair<PartitionKey, Stream> keyValue = new KeyValuePair<PartitionKey, Stream>(new PartitionKey(o.ToString()), stream);
+                    itemsToInsert.Add(keyValue);
+                });
+                List<Task> tasks = new List<Task>(lists.Count);
+                itemsToInsert.ForEach(item =>
+                {
+                    tasks.Add(container.container.UpsertItemStreamAsync(item.Value, item.Key)
+                        .ContinueWith((Task<Response> task) =>
+                        {
+                        }
+                        ));
+                });
+                await Task.WhenAll(tasks);
+                if (container.cache && RedisHelper.Instance != null)
+                {
+                    lists.ForEach(async x => {
+                        await RedisHelper.HSetAsync(CacheCosmosPrefix + container.container.Id, x.id, x);
+                    });
+                }
+            }
+            if (container.cache && RedisHelper.Instance != null && !flag)
+            {
+                await RedisHelper.ExpireAsync(CacheCosmosPrefix + container.container.Id, timeoutSeconds);
+            }
+            stopwatch.Stop();
+            return enyites;
+        }
+        public static async Task<List<int>> FindCountByDict<T>(this AzureCosmosFactory azureCosmosFactory, Dictionary<string, object> dict)
+        {
+            Type type = typeof(T);
+            AzureCosmosModel container = azureCosmosFactory.GetCosmosModel(type.Name);
+            string pk = type.Name;
+            StringBuilder sql = new StringBuilder("select  value count(c)  from c");
+            AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql, pk);
+            if (cosmosDbQuery == null)
+            {
+                return new List<int> { 0 };
+            }
+            QueryRequestOptions queryRequestOptions = GetDefaultQueryRequestOptions(itemsPerPage: GetEffectivePageSize(-1, null));
+            AsyncPageable<int> query = container.container.GetItemQueryIterator<int>(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: queryRequestOptions);
+            return await ResultsFromFeedIterator(query);
+        }
+        public static async Task<List<dynamic>> FindCountByDict(this AzureCosmosFactory azureCosmosFactory, string CollectionName, Dictionary<string, object> dict)
+        {
+            if (azureCosmosFactory.CosmosDict.typeCosmos.TryGetValue(CollectionName, out AzureCosmosModel container))
+            {
+                string pk = container.type.Name;
+                dict.Remove("@CURRPAGE");
+                dict.Remove("@PAGESIZE");
+                dict.Remove("@ASC");
+                dict.Remove("@DESC");
+                StringBuilder sql = new StringBuilder("select  value count(c)  from c");
+                AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql, pk);
+                if (cosmosDbQuery == null)
+                {
+                    return new List<dynamic> { 0 };
+                }
+                QueryRequestOptions queryRequestOptions = GetDefaultQueryRequestOptions(itemsPerPage: GetEffectivePageSize(-1, null));
+                AsyncPageable<dynamic> query = container.container.GetItemQueryIterator<dynamic>(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: queryRequestOptions);
+                return await ResultsFromFeedIterator(query);
+            }
+            else
+            {
+                throw new BizException("CollectionName named:" + CollectionName + " dose not exsit in Database!");
+            }
+        }
+        public static async Task<T> Update<T>(this AzureCosmosFactory azureCosmosFactory,  T entity) where T : ID
+        {
+            Type type = typeof(T);
+            AzureCosmosModel container = azureCosmosFactory.GetCosmosModel(type.Name);
+            string partitionKey =AzureCosmosUtil.GetPartitionKey (type);
+            entity.pk = type.Name;
+            entity.ttl = -1;
+            object o = type.GetProperty(partitionKey).GetValue(entity, null);
+            ItemResponse<T> response = await container.container.ReplaceItemAsync(entity, entity.id, new PartitionKey(o.ToString()));
+            if (container.cache && RedisHelper.Instance != null)
+            {
+                if (!RedisHelper.Exists(CacheCosmosPrefix + container.container.Id))
+                {
+                    await RedisHelper.HSetAsync(CacheCosmosPrefix + container.container.Id, entity.id, entity);
+                }
+                else
+                {
+                    await RedisHelper.HSetAsync(CacheCosmosPrefix + container.container.Id, entity.id, entity);
+                    await RedisHelper.ExpireAsync(CacheCosmosPrefix + container.container.Id, timeoutSeconds);
+                }
+            }
+            return response.Value;
+        }
+        internal class Item
+        {
+            public string id { get; set; }
+            public string pk { get; set; }
+            public MemoryStream stream { get; set; }
+        } 
+        public static async Task<List<T>> UpdateAll<T>(this AzureCosmosFactory azureCosmosFactory,  List<T> enyites) where T : ID
+        {
+            //await Task.Run(() => Parallel.ForEach(entities, new ParallelOptions { MaxDegreeOfParallelism = 2 }, (item) =>
+            //{
+            //    Task.WaitAll(Update(item));
+            //}));
+            Type type = typeof(T);
+            int pages = (int)Math.Ceiling((double)enyites.Count / pageSize);
+            AzureCosmosModel container = azureCosmosFactory.GetCosmosModel(type.Name);
+            bool flag = false;
+            if (RedisHelper.Exists(CacheCosmosPrefix + container.container.Id))
+            {
+                flag = true;
+            }
+            string partitionKey =AzureCosmosUtil.GetPartitionKey (type);
+           
+            Stopwatch stopwatch = Stopwatch.StartNew();
+            for (int i = 0; i < pages; i++)
+            {
+                List<T> lists = enyites.Skip((i) * pageSize).Take(pageSize).ToList();
+                List<Item> itemsToInsert = new List<Item>();
+                lists.ForEach(async x =>
+                {
+                    x.pk = type.Name;
+                    x.ttl = -1;
+                    MemoryStream stream = new MemoryStream();
+                    await JsonSerializer.SerializeAsync(stream, x, new JsonSerializerOptions { IgnoreNullValues = true });
+                    object o = type.GetProperty(partitionKey).GetValue(x, null);
+                    Item keyValue = new Item { id = x.id, pk = o.ToString(), stream = stream };
+                    itemsToInsert.Add(keyValue);
+                });
+                List<Task> tasks = new List<Task>(lists.Count);
+                itemsToInsert.ForEach(item =>
+                {
+                    tasks.Add(container.container.ReplaceItemStreamAsync(item.stream, item.id, new PartitionKey(item.pk))
+                        .ContinueWith((Task<Response> task) =>
+                        {
+                            //using (ResponseMessage response = task.Result)
+                            //{
+                            //    if (!response.IsSuccessStatusCode)
+                            //    {
+                            //    }
+                            //}
+                        }
+                        ));
+                });
+                await Task.WhenAll(tasks);
+                if (container.cache && RedisHelper.Instance != null)
+                {
+                    lists.ForEach(async x => {
+                        await RedisHelper.HSetAsync(CacheCosmosPrefix + container.container.Id, x.id, x);
+                    });
+                }
+            }
+            if (container.cache && RedisHelper.Instance != null && !flag)
+            {
+                await RedisHelper.ExpireAsync(CacheCosmosPrefix + container.container.Id, timeoutSeconds);
+            }
+            stopwatch.Stop();
+            return enyites;
+        }
+        public static async Task<List<T>> FindByDict<T>(this AzureCosmosFactory azureCosmosFactory, Dictionary<string, object> dict, List<string> propertys = null) where T : ID
+        {
+            StringBuilder sql;
+            sql = SQLHelper.GetSQLSelect(propertys);
+            string pk = typeof(T).Name;
+            AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql, pk);
+            QueryRequestOptions queryRequestOptions = GetDefaultQueryRequestOptions(itemsPerPage: GetEffectivePageSize(-1, null));
+            return await ResultsFromQueryAndOptions<T>(azureCosmosFactory,cosmosDbQuery, queryRequestOptions);
+        }
+        public static async Task<List<dynamic>> FindByDict(this AzureCosmosFactory azureCosmosFactory, string CollectionName, Dictionary<string, object> dict, List<string> propertys = null)
+        {
+            if (azureCosmosFactory.CosmosDict.typeCosmos.TryGetValue(CollectionName, out AzureCosmosModel container))
+            {
+
+                string pk = container.type.Name;
+                StringBuilder sql;
+                sql = SQLHelper.GetSQLSelect(propertys);
+                AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql, pk);
+                QueryRequestOptions queryRequestOptions = GetDefaultQueryRequestOptions(itemsPerPage: GetEffectivePageSize(-1, null));
+                AsyncPageable<dynamic> query = container.container.GetItemQueryIterator<dynamic>(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: queryRequestOptions);
+                return await ResultsFromFeedIterator(query);
+            }
+            else
+            {
+                throw new BizException("CollectionName named:" + CollectionName + " dose not exsit in Database!");
+            }
+        }
+        public static async Task<List<IdPk>> DeleteAll<T>(this AzureCosmosFactory azureCosmosFactory, List<IdPk> ids) where T : ID
+        {
+            AzureCosmosModel container = azureCosmosFactory.GetCosmosModel(typeof(T).Name);
+            List<IdPk> idPks = new List<IdPk>();
+            if (container.monitor)
+            {
+                List<T> list = await azureCosmosFactory.FindByDict<T>(new Dictionary<string, object>() { { "id", ids.Select(x => x.id).ToArray() } });
+                list = await azureCosmosFactory. DeleteTTL(list);
+                return ids;
+            }
+            else
+            {
+                int pages = (int)Math.Ceiling((double)ids.Count / pageSize);
+                Stopwatch stopwatch = Stopwatch.StartNew();
+                for (int i = 0; i < pages; i++)
+                {
+                    List<IdPk> lists = ids.Skip((i) * pageSize).Take(pageSize).ToList();
+                    List<Task> tasks = new List<Task>(lists.Count);
+                    lists.ForEach(item =>
+                    {
+                        tasks.Add(container.container.DeleteItemStreamAsync(item.id, new PartitionKey(item.pk))
+                            .ContinueWith((Task<Response> task) =>
+                            {
+                                using (Response response = task.Result)
+                                {
+                                    idPks.Add(new IdPk { id = item.id, pk = item.pk, Status = response.Status });
+                                    //    if (!response.IsSuccessStatusCode)
+                                    //    {
+                                    //    }
+                                }
+                            }
+                            ));
+                    });
+                    await Task.WhenAll(tasks);
+                    if (container.cache && RedisHelper.Instance != null)
+                    {
+                        lists.ForEach(async x => {
+                            await RedisHelper.HDelAsync(CacheCosmosPrefix + container.container.Id, x.id);
+                        });
+                    }
+                }
+                stopwatch.Stop();
+                return idPks;
+            }
+        }
+        public static async Task<List<IdPk>> DeleteAll<T>(this AzureCosmosFactory azureCosmosFactory, Dictionary<string, object> dict) where T : ID
+        {
+            if (dict.Keys.Count > 0)
+            {
+                List<T> list = await azureCosmosFactory.FindByDict<T>(dict);
+
+                return await azureCosmosFactory.DeleteAll(list);
+            }
+            else
+            {
+                throw new BizException("参数为空", 500);
+            }
+
+        }
+        public static async Task<List<IdPk>> DeleteAll<T>(this AzureCosmosFactory azureCosmosFactory, List<T> enyites) where T : ID
+        {
+            Type type = typeof(T);
+            AzureCosmosModel container =   azureCosmosFactory.GetCosmosModel (type.Name);
+            List<IdPk> idPks = new List<IdPk>();
+            //log4net 日志記錄
+            string uuidKey = Guid.NewGuid().ToString();
+            string logkey = "\r\n【" + uuidKey + "】\r\n";
+            LogHelper.Info(new object(),
+                           logkey
+                           + "删除------->>\r\n"
+                           + "表:"
+                           + type.Name + "\r\n"
+                           + "数据:"
+                           + enyites.ToApiJson()
+                           + "\r\n" + logkey);
+            string pk = AzureCosmosUtil.GetPartitionKey (type);
+            if (container.monitor)
+            {
+                enyites = await azureCosmosFactory.DeleteTTL(enyites);
+                foreach (T t in enyites)
+                {
+                    object o = type.GetProperty(pk).GetValue(t, null);
+                    idPks.Add(new IdPk { id = t.id, pk = o.ToString(), StatusCode = HttpStatusCode.NoContent });
+                }
+                return idPks;
+            }
+            else
+            {
+                int pages = (int)Math.Ceiling((double)enyites.Count / pageSize);
+                Stopwatch stopwatch = Stopwatch.StartNew();
+                for (int i = 0; i < pages; i++)
+                {
+                    List<T> lists = enyites.Skip((i) * pageSize).Take(pageSize).ToList();
+                    List<KeyValuePair<PartitionKey, string>> itemsToInsert = new List<KeyValuePair<PartitionKey, string>>();
+                    lists.ForEach(x =>
+                    {
+                        object o = type.GetProperty(pk).GetValue(x, null);
+                        KeyValuePair<PartitionKey, string> keyValue = new KeyValuePair<PartitionKey, string>(new PartitionKey(o.ToString()), x.id);
+                        itemsToInsert.Add(keyValue);
+                    });
+
+                    List<Task> tasks = new List<Task>(lists.Count);
+                    itemsToInsert.ForEach(item =>
+                    {
+                        tasks.Add(container.container.DeleteItemStreamAsync(item.Value, item.Key)
+                        .ContinueWith((Task<Response> task) =>
+                        {
+                            using (Response response = task.Result)
+                            {
+
+                                idPks.Add(new IdPk { id = item.Value, pk = item.Key.ToString(), Status = response.Status });
+
+                            }
+                        }
+                        ));
+                    });
+                    await Task.WhenAll(tasks); if (container.cache && RedisHelper.Instance != null)
+                    {
+                        lists.ForEach(async x => {
+                            await RedisHelper.HDelAsync(CacheCosmosPrefix + container.container.Id, x.id);
+                        });
+                    }
+                }
+                stopwatch.Stop();
+                return idPks;
+            }
+        }
+        public static async Task<IdPk> DeleteAsync<T>(this AzureCosmosFactory azureCosmosFactory, IdPk idPk) where T : ID
+        {
+            return await DeleteAsync<T>(azureCosmosFactory, idPk.id, idPk.pk);
+        }
+        public static async Task<IdPk> DeleteAsync<T>(this AzureCosmosFactory azureCosmosFactory, string id, string pk) where T : ID
+        {
+
+            //  pk =AzureCosmosUtil.GetPartitionKey<T>();
+            AzureCosmosModel container = azureCosmosFactory.GetCosmosModel(typeof(T).Name);
+            if (container.monitor)
+            {
+                List<T> list = await FindByDict<T>(azureCosmosFactory,new Dictionary<string, object>() { { "id", id } });
+                if (list.Count > 0)
+                {
+                    await DeleteTTL<T>(azureCosmosFactory, list);
+                    return new IdPk { id = id, pk = pk, StatusCode = HttpStatusCode.NoContent };
+                }
+                else
+                {
+                    throw new BizException("未找到ID匹配的数据,删除失败");
+                }
+            }
+            else
+            {
+                Response response = await container.container.DeleteItemStreamAsync(id: id, partitionKey: new PartitionKey(pk));
+                if (container.cache && RedisHelper.Instance != null)
+                {
+                    await RedisHelper.HDelAsync(CacheCosmosPrefix + container.container.Id, id);
+                }
+                return new IdPk { id = id, pk = pk, Status = response.Status };
+            }
+
+        }
+        public static async Task<IdPk> DeleteAsync<T>(this AzureCosmosFactory azureCosmosFactory, T entity) where T : ID
+        {
+            Type type = typeof(T);
+            AzureCosmosModel container =   azureCosmosFactory.GetCosmosModel(type.Name);
+            string partitionKey = AzureCosmosUtil.GetPartitionKey (type);
+           
+            object o = type.GetProperty(partitionKey).GetValue(entity, null);
+            if (container.monitor)
+            {
+                await DeleteTTL<T>(azureCosmosFactory, new List<T>() { entity });
+                return new IdPk { id = entity.id, pk = o.ToString(), StatusCode = HttpStatusCode.NoContent };
+            }
+            else
+            {
+                Response response = await container.container.DeleteItemStreamAsync(id: entity.id, partitionKey: new PartitionKey(o.ToString()));
+                if (container.cache && RedisHelper.Instance != null)
+                {
+                    await RedisHelper.HDelAsync(CacheCosmosPrefix + container.container.Id, entity.id);
+                }
+                return new IdPk { id = entity.id, pk = partitionKey, Status = response.Status };
+            }
+        }
+        public static async Task<List<T>> FindSQL<T>(this AzureCosmosFactory azureCosmosFactory, string sql, Dictionary<string, object> Parameters = null) where T : ID
+        {
+            if (sql.Contains(".pk"))
+            {
+                AzureCosmosModel container = azureCosmosFactory.GetCosmosModel(typeof(T).Name);
+                QueryRequestOptions queryOptions = GetQueryRequestOptions(GetEffectivePageSize(-1, null));
+                if (Parameters != null)
+                {
+                    AzureCosmosQuery cosmosDbQuery = new AzureCosmosQuery
+                    {
+                        QueryText = sql,
+                        Parameters = Parameters
+                    };
+                    AsyncPageable<T> feedIterator = container.container
+                    .GetItemQueryIterator<T>(cosmosDbQuery.CosmosQueryDefinition, requestOptions: queryOptions);
+                    return await ResultsFromFeedIterator(feedIterator);
+                }
+                else
+                {
+                    QueryDefinition queryDefinition = new QueryDefinition(sql);
+                    return await ResultsFromFeedIterator<T>(container.container.GetItemQueryIterator<T>(queryDefinition));
+                }
+            }
+            else
+            {
+                throw new BizException("查询参数必须设置 .pk ", ResponseCode.PARAMS_ERROR);
+            }
+        }
+        /// <summary>
+        /// 偌TTL刉壺
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="list"></param>
+        /// <returns></returns>
+        private static  async Task<List<T>> DeleteTTL<T>(this AzureCosmosFactory azureCosmosFactory ,List<T> list) where T : ID
+        {
+            AzureCosmosModel container = azureCosmosFactory.GetCosmosModel(typeof(T).Name);
+            list.ForEach(x => { x.ttl = ttl; });
+            list = await DeleteTTlALL(azureCosmosFactory,list);
+            if (container.cache && RedisHelper.Instance != null)
+            {
+                list.ForEach(async x => {
+                    await RedisHelper.HDelAsync(CacheCosmosPrefix + container.container.Id, x.id);
+                });
+            }
+            return list;
+        }
+        private static  async Task<List<T>> DeleteTTlALL<T>(this AzureCosmosFactory azureCosmosFactory, List<T> enyites) where T : ID
+        {
+            Type type = typeof(T);
+            int pages = (int)Math.Ceiling((double)enyites.Count / pageSize);
+            AzureCosmosModel container = azureCosmosFactory.GetCosmosModel(type.Name);
+            bool flag = false;
+            if (RedisHelper.Exists(CacheCosmosPrefix + container.container.Id))
+            {
+                flag = true;
+            }
+            string partitionKey = AzureCosmosUtil.GetPartitionKey (type);
+           
+            Stopwatch stopwatch = Stopwatch.StartNew();
+            for (int i = 0; i < pages; i++)
+            {
+                List<T> lists = enyites.Skip((i) * pageSize).Take(pageSize).ToList();
+                List<KeyValuePair<PartitionKey, Stream>> itemsToInsert = new List<KeyValuePair<PartitionKey, Stream>>();
+                lists.ForEach(async x =>
+                {
+                    x.pk = type.Name;
+                    //x.ttl = null;
+                    MemoryStream stream = new MemoryStream();
+                    await JsonSerializer.SerializeAsync(stream, x, new JsonSerializerOptions { IgnoreNullValues = true });
+                    object o = type.GetProperty(partitionKey).GetValue(x, null);
+                    KeyValuePair<PartitionKey, Stream> keyValue = new KeyValuePair<PartitionKey, Stream>(new PartitionKey(o.ToString()), stream);
+                    itemsToInsert.Add(keyValue);
+                });
+                List<Task> tasks = new List<Task>(lists.Count);
+                itemsToInsert.ForEach(item =>
+                {
+                    tasks.Add(container.container.UpsertItemStreamAsync(item.Value, item.Key)
+                        .ContinueWith((Task<Response> task) =>
+                        {
+                            //using (ResponseMessage response = task.Result)
+                            //{
+                            //    if (!response.IsSuccessStatusCode)
+                            //    {
+                            //    }
+                            //}
+                        }
+                        ));
+                });
+                await Task.WhenAll(tasks);
+                if (container.cache && RedisHelper.Instance != null)
+                {
+                    lists.ForEach(async x => {
+                        await RedisHelper.HSetAsync(CacheCosmosPrefix + container.container.Id, x.id, x);
+                    });
+                }
+            }
+            if (container.cache && RedisHelper.Instance != null && !flag)
+            {
+                await RedisHelper.ExpireAsync(CacheCosmosPrefix + container.container.Id, timeoutSeconds);
+            }
+            stopwatch.Stop();
+            return enyites;
+        }
+        private static QueryRequestOptions GetDefaultQueryRequestOptions(int? itemsPerPage = null, int? maxBufferedItemCount = null,  int? maxConcurrency = null)
+        {
+            QueryRequestOptions queryRequestOptions = new QueryRequestOptions
+            {
+                MaxItemCount = itemsPerPage == -1 ? 1000 : itemsPerPage,
+                MaxBufferedItemCount = maxBufferedItemCount ?? 100,
+                MaxConcurrency = maxConcurrency ?? 50
+            };
+            return queryRequestOptions;
+        }
+        private static int GetEffectivePageSize(int itemsPerPage, int? maxItemCount)
+        {
+            return itemsPerPage == -1 ? maxItemCount ?? itemsPerPage : Math.Min(maxItemCount ?? itemsPerPage, itemsPerPage);
+        }
+        private static async Task<List<T>> ResultsFromQueryAndOptions<T>(this AzureCosmosFactory azureCosmosFactory, AzureCosmosQuery cosmosDbQuery, QueryRequestOptions queryOptions)
+        {
+            if (cosmosDbQuery == null)
+            {
+                return null;
+            }
+            AzureCosmosModel container = azureCosmosFactory.GetCosmosModel(typeof(T).Name);
+            AsyncPageable<T> query = container.container.GetItemQueryIterator<T>(
+                queryDefinition: cosmosDbQuery.CosmosQueryDefinition,
+                requestOptions: queryOptions);
+
+            return await ResultsFromFeedIterator(query);
+        }
+        private static async Task<List<T>> ResultsFromFeedIterator<T>(AsyncPageable<T> query, int? maxItemCount = null)
+        {
+            List<T> results = new List<T>();
+             
+            await  foreach (T t in   query)
+            {
+                results.Add(t);
+                if (results.Count == maxItemCount)
+                {
+                    return results;
+                }
+            }
+            return results;
+        }
+        private static QueryRequestOptions GetQueryRequestOptions(int itemsPerPage)
+        {
+            QueryRequestOptions queryRequestOptions = new QueryRequestOptions
+            {
+                MaxItemCount = itemsPerPage
+            };
+
+            return queryRequestOptions;
+        }
+    }
+}

+ 207 - 0
TEAMModelOS.SDK/DI/AzureCosmos/AzureCosmosFactory.cs

@@ -0,0 +1,207 @@
+using Azure;
+using Azure.Cosmos;
+using DocumentFormat.OpenXml.Office2010.ExcelAc;
+using Microsoft.Azure.Cosmos;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using TEAMModelOS.Models;
+using TEAMModelOS.SDK.Context.Attributes.Azure;
+using TEAMModelOS.SDK.Context.Configuration;
+using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
+using TEAMModelOS.SDK.Helper.Common.ReflectorExtensions;
+using ContainerProperties = Azure.Cosmos.ContainerProperties;
+using CosmosClient = Azure.Cosmos.CosmosClient;
+using CosmosClientOptions = Azure.Cosmos.CosmosClientOptions;
+using OpenXmlPowerTools;
+using System.Diagnostics;
+using System.IO;
+using System.Linq.Expressions;
+using System.Net;
+using System.Reflection;
+using System.Text;
+using System.Text.Json;
+using System.Threading;
+using TEAMModelOS.SDK.Context.Exception;
+using TEAMModelOS.SDK.DI;
+using PartitionKey = Azure.Cosmos.PartitionKey;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public class AzureCosmosFactory
+    {
+        private readonly IServiceProvider _services;
+        private readonly IOptionsMonitor<AzureCosmosFactoryOptions> _optionsMonitor;
+        private readonly ILogger _logger;
+        //private Option _option;
+        private ConcurrentDictionary<string, CosmosClient> CosmosClients { get; } = new ConcurrentDictionary<string, CosmosClient>();
+        public AzureCosmosDict CosmosDict { get; set; } = new AzureCosmosDict();
+        //   private CosmosDatabase database { get; set; }
+        
+        public AzureCosmosFactory(IServiceProvider services, IOptionsMonitor<AzureCosmosFactoryOptions> optionsMonitor, ILogger<AzureCosmosFactory> logger)
+        {
+            if (services == null) throw new ArgumentNullException(nameof(services));
+            if (optionsMonitor == null) throw new ArgumentNullException(nameof(optionsMonitor));
+
+            _services = services;
+            _optionsMonitor = optionsMonitor;
+            _logger = logger;
+           
+            InitializeDatabase().GetAwaiter().GetResult();
+        }
+
+        /// <summary>
+        /// 取得CosmosClient,支持安全執行緒
+        /// </summary>
+        /// <param name="name"></param>
+        /// <param name="region">可以使用Regions.{區域}設置,指定此屬性後,SDK會首選該區域來執行操作。此外,SDK會自動選擇後備的地理複製區域以實現高可用性。如果未指定此屬性,則SDK會將寫區域用作所有操作的首選區域</param>
+        /// <returns></returns>
+        public CosmosClient GetCosmosClient(string region = null, string name = "Default")
+        {
+            try
+            {
+                var cm = CosmosClients.GetOrAdd(name, x => new CosmosClient(_optionsMonitor.Get(name).CosmosConnectionString, new CosmosClientOptions() { ApplicationRegion = region }));
+                return cm;
+            }
+            catch (Exception e)
+            {
+                _logger?.LogWarning(e, e.Message);
+                return null;
+            }
+        }
+         
+        /// <summary>
+        /// 获取容器信息
+        /// </summary>
+        /// <param name="cosmosDBAttribute"></param>
+        /// <param name="typeName"></param>
+        /// <param name="PartitionKey"></param>
+        /// <returns></returns>
+        public AzureCosmosModel GetCosmosModel( string typeName )
+        {
+            /////内存中已经存在这个表则直接返回
+            if (CosmosDict.typeCosmos.TryGetValue(typeName, out AzureCosmosModel AzureCosmosModel))
+            {
+                return AzureCosmosModel;
+            }
+            else {
+                return null;
+            }
+          
+        }
+        /// <summary>
+        /// 初始化数据配置信息
+        /// </summary>
+        /// <returns></returns>
+        public async Task InitializeDatabase()
+        {
+            int CollectionThroughput = 400;
+            string[] DatabaseIds = BaseConfigModel.Configuration.GetSection("Azure:Cosmos:Database").Get<string[]>();
+            bool isMonitor = false;
+            string leases = "leases";
+            if (DatabaseIds != null)
+            {
+                foreach (string DatabaseId in DatabaseIds)
+                {
+                    CosmosDatabase databaseDef = GetCosmosClient().GetDatabase(DatabaseId);
+                    AsyncPageable<ContainerProperties> resultSetIterator = databaseDef.GetContainerQueryIterator<ContainerProperties>();
+                    await foreach (var container in resultSetIterator)
+                    {
+                        CosmosDict.nameCosmos.TryAdd(container.Id, new AzureCosmosModel { container = databaseDef.GetContainer(container.Id), partitionKey = container.PartitionKeyPath.Replace("/", ""), cache = false, monitor = false, database = databaseDef });
+                    }
+                }
+            }
+            //获取数据库所有的表
+            List<Type> types = ReflectorExtensions.GetAllTypeAsAttribute<CosmosDBAttribute>(BaseConfigModel.Configuration.GetSection("Azure:Cosmos:ScanModel").Get<string[]>() );
+            foreach (Type type in types)
+            {
+                string PartitionKey = AzureCosmosUtil.GetPartitionKey(type);
+                string CollectionName = "";
+                int RU = 0;
+                bool cache = false;
+                bool monitor = false;
+                IEnumerable<CosmosDBAttribute> attributes = type.GetCustomAttributes<CosmosDBAttribute>(true);
+                if (attributes != null && !string.IsNullOrEmpty(attributes.First<CosmosDBAttribute>().Name))
+                {
+                    CollectionName = attributes.First<CosmosDBAttribute>().Name;
+                }
+                else
+                {
+                    throw new BizException("必须指定容器名", ResponseCode.PARAMS_ERROR);
+                }
+                if (attributes.First<CosmosDBAttribute>().Cache)
+                {
+                    cache = attributes.First<CosmosDBAttribute>().Cache;
+                }
+                if (attributes.First<CosmosDBAttribute>().Monitor)
+                {
+                    monitor = attributes.First<CosmosDBAttribute>().Monitor;
+                    if (monitor)
+                    {
+                        isMonitor = true;
+                    }
+                }
+                if (attributes.First<CosmosDBAttribute>().RU > 400)
+                {
+                    RU = attributes.First<CosmosDBAttribute>().RU;
+                }
+                else
+                {
+                    RU = CollectionThroughput;
+                }
+                //如果表存在于数据则检查RU是否变动,如果不存在则执行创建DocumentCollection
+                if (CosmosDict.nameCosmos.TryGetValue(CollectionName, out AzureCosmosModel AzureCosmosModel))
+                { //更新RU
+
+                    AzureCosmosModel.cache = cache;
+                    CosmosContainer container = GetCosmosClient().GetDatabase(attributes.First().Database).GetContainer(AzureCosmosModel.container.Id);
+                    int? throughputResponse = await container.ReadThroughputAsync();
+                    if (throughputResponse < RU)
+                    {
+                        await GetCosmosClient().GetDatabase(attributes.First().Database).GetContainer(AzureCosmosModel.container.Id).ReplaceThroughputAsync(RU);
+                    }
+                    AzureCosmosModel cosmos = new AzureCosmosModel { container = container, cache = cache, monitor = monitor, type = type, partitionKey = PartitionKey };
+                    CosmosDict.nameCosmos[CollectionName] = cosmos;
+                    CosmosDict.typeCosmos.Add(type.Name, cosmos);
+                }
+                else
+                {
+                    ContainerProperties containerProperties = new ContainerProperties { Id = CollectionName, DefaultTimeToLive = -1 };
+                    if (!string.IsNullOrEmpty(PartitionKey))
+                    {
+                        containerProperties.PartitionKeyPath = "/" + PartitionKey;
+                    }
+                    if (RU > CollectionThroughput)
+                    {
+                        CollectionThroughput = RU;
+                    }
+                    CosmosDatabase database = GetCosmosClient().GetDatabase(attributes.First().Database);
+                    CosmosContainer containerWithConsistentIndexing =await database.CreateContainerIfNotExistsAsync(containerProperties, throughput: CollectionThroughput);
+                    AzureCosmosModel cosmos = new AzureCosmosModel { container = containerWithConsistentIndexing, cache = cache, monitor = monitor, type = type, partitionKey = PartitionKey,database=database };
+                    CosmosDict.nameCosmos[CollectionName] = cosmos;
+                    CosmosDict.typeCosmos.Add(type.Name, cosmos);
+                }
+            }
+            if (isMonitor)
+            {
+                if (DatabaseIds != null)
+                {
+                    foreach (string DatabaseId in DatabaseIds)
+                    {
+                        CosmosDatabase database = GetCosmosClient().GetDatabase(DatabaseId);
+                        ContainerProperties leaseProperties = new ContainerProperties { Id = leases, PartitionKeyPath = "/id", DefaultTimeToLive = -1 };
+                        CosmosContainer leaseContainer = await database.CreateContainerIfNotExistsAsync(leaseProperties, throughput: CollectionThroughput);
+                        CosmosDict.nameCosmos.TryAdd(leases, new AzureCosmosModel { container = leaseContainer, cache = false, monitor = false, partitionKey = "/id", database = database });
+                    }
+                }
+
+            }
+        }
+        
+    }
+}

+ 20 - 0
TEAMModelOS.SDK/DI/AzureCosmos/AzureCosmosFactoryExtensions.cs

@@ -0,0 +1,20 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public static class AzureCosmosFactoryExtensions
+    {
+        public static IServiceCollection AddAzureCosmos(this IServiceCollection services, string connectionString, string name = "Default")
+        {
+            if (services == null) throw new ArgumentNullException(nameof(services));            
+            if (connectionString == null) throw new ArgumentNullException(nameof(connectionString));
+            services.TryAddSingleton<AzureCosmosFactory>();
+            services.Configure<AzureCosmosFactoryOptions>(name, o => { o.Name = name; o.CosmosConnectionString = connectionString; });
+            return services;
+        }
+    }
+}

+ 14 - 0
TEAMModelOS.SDK/DI/AzureCosmos/AzureCosmosFactoryOptions.cs

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public class AzureCosmosFactoryOptions
+    {
+        public string Name { get; set; }
+        public string CosmosConnectionString { get; set; }
+    }
+
+   
+}

+ 18 - 0
TEAMModelOS.SDK/DI/AzureCosmos/Inner/AzureCosmosDict.cs

@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.DI.AzureCosmos.Inner
+{
+    public class AzureCosmosDict
+    {
+        /// <summary>
+        /// 表名方式的连接
+        /// </summary>
+        public Dictionary<string, AzureCosmosModel> nameCosmos { get; set; } = new Dictionary<string, AzureCosmosModel>();
+        /// <summary>
+        /// 类类型的连接
+        /// </summary>
+        public Dictionary<string, AzureCosmosModel> typeCosmos { get; set; } = new Dictionary<string, AzureCosmosModel>();
+    }
+}

+ 6 - 4
TEAMModelOS.SDK/Module/AzureCosmosDBV3/CosmosModelInfo.cs

@@ -1,16 +1,18 @@
-using Microsoft.Azure.Cosmos;
+using Azure.Cosmos;
+using Microsoft.Azure.Cosmos;
 using System;
 using System.Collections.Generic;
 using System.Text;
 
-namespace TEAMModelOS.SDK.Module.AzureCosmosDBV3
+namespace TEAMModelOS.SDK.DI.AzureCosmos.Inner
 {
-    public class CosmosModelInfo
+    public class AzureCosmosModel
     {
-        public Container container { get; set; }
+        public CosmosContainer container { get; set; }
         public bool cache { get; set; }
         public bool monitor { get; set; } = false;
         public Type type { get; set; }
         public string partitionKey { get; set; }
+        public CosmosDatabase database { get; set; }
     }
 }

+ 6 - 6
TEAMModelOS.SDK/Module/AzureCosmosDBV3/CosmosDbQuery.cs

@@ -1,11 +1,11 @@
-using Microsoft.Azure.Cosmos;
+using Azure.Cosmos;
 using System;
 using System.Collections.Generic;
 using System.Text;
 
-namespace TEAMModelOS.SDK.Module.AzureCosmosDBV3
+namespace TEAMModelOS.SDK.DI.AzureCosmos.Inner
 {
-   public class CosmosDbQuery
+    public   class AzureCosmosQuery
     {
         public string QueryText { get; set; }
 
@@ -29,14 +29,14 @@ namespace TEAMModelOS.SDK.Module.AzureCosmosDBV3
             }
         }
 
-        public CosmosDbQuery() { }
+        public AzureCosmosQuery() { }
 
-        public CosmosDbQuery(string queryText)
+        public AzureCosmosQuery(string queryText)
         {
             QueryText = queryText;
         }
 
-        public CosmosDbQuery(string queryText, Dictionary<string, object> parameters)
+        public AzureCosmosQuery(string queryText, Dictionary<string, object> parameters)
         {
             QueryText = queryText;
             Parameters = parameters;

+ 46 - 0
TEAMModelOS.SDK/DI/AzureCosmos/Inner/AzureCosmosUtil.cs

@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Text;
+using TEAMModelOS.SDK.Context.Attributes.Azure;
+using TEAMModelOS.SDK.Context.Exception;
+
+namespace TEAMModelOS.SDK.DI.AzureCosmos.Inner
+{
+   public static class AzureCosmosUtil
+    {
+        public static string GetPartitionKey(Type type)
+        {
+            PropertyInfo[] properties = type.GetProperties();
+            List<PropertyInfo> attrProperties = new List<PropertyInfo>();
+            foreach (PropertyInfo property in properties)
+            {
+                if (property.Name.Equals("PartitionKey"))
+                {
+                    attrProperties.Add(property);
+                    break;
+                }
+                object[] attributes = property.GetCustomAttributes(true);
+                foreach (object attribute in attributes) //2.通过映射,找到成员属性上关联的特性类实例,
+                {
+                    if (attribute is PartitionKeyAttribute)
+                    {
+                        attrProperties.Add(property);
+                    }
+                }
+            }
+            if (attrProperties.Count <= 0)
+            {
+                throw new BizException(type.Name + " has no PartitionKey !");
+            }
+            else
+            {
+                if (attrProperties.Count == 1)
+                {
+                    return attrProperties[0].Name;
+                }
+                else { throw new BizException(type.Name + " PartitionKey can only be single!"); }
+            }
+        }
+    }
+}

+ 3 - 3
TEAMModelOS.SDK/Module/AzureCosmosDBV3/ID.cs

@@ -1,13 +1,13 @@
-using System;
+using System;
 using System.Collections.Generic;
 using System.Text;
 using System.Text.Json.Serialization;
 
-namespace TEAMModelOS.SDK.Module.AzureCosmosDBV3
+namespace TEAMModelOS.SDK.DI
 {
     public interface ID
     {
-        int? ttl { get; set; }
+        int? ttl { get; set; } 
         string pk { get; set; }
         string id { get; set; }
         string code { get; set; }

+ 6 - 1
TEAMModelOS.SDK/Module/AzureCosmosDBV3/IdPk.cs

@@ -6,7 +6,7 @@ using System.Linq;
 using System.Net;
 using System.Threading.Tasks;
 
-namespace TEAMModelOS.SDK.Module.AzureCosmosDBV3
+namespace TEAMModelOS.SDK.DI
 {
     [ProtoContract]
     public class IdPk
@@ -23,5 +23,10 @@ namespace TEAMModelOS.SDK.Module.AzureCosmosDBV3
         /// </summary>
         [ProtoMember(3)]
         public HttpStatusCode StatusCode { get;set;}
+        /// <summary>
+        /// 删除状态 NoContent(删除成功),NotFound(未找到,删除失败)
+        /// </summary>
+        [ProtoMember(3)]
+        public int Status { get; set; }
     }
 }

+ 28 - 23
TEAMModelOS.SDK/Module/AzureCosmosDBV3/SQLHelperParametric.cs

@@ -8,10 +8,9 @@ using System.Text.Json;
 using System.Text.RegularExpressions;
 using TEAMModelOS.SDK.Context.Exception;
 using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
-
-namespace TEAMModelOS.SDK.Module.AzureCosmosDBV3
+namespace TEAMModelOS.SDK.DI.AzureCosmos.Inner
 {
-    public class SQLHelperParametric
+   public class SQLHelper
     {
         static readonly string[] LogicOpers = new string[] { " and ", " or " };
         static readonly string[] CompareOpers = new string[] { " > ", " < ", " <= ", " >= ", " = ", " != ", " like ", " not like ", " in " };
@@ -73,7 +72,7 @@ namespace TEAMModelOS.SDK.Module.AzureCosmosDBV3
 
         public static bool DictIsNotNULL(Dictionary<string, object> dict)
         {
-             
+
             Dictionary<string, object> keyValuePairs = new Dictionary<string, object>();
             foreach (KeyValuePair<string, object> keyValuePair in dict)
             {
@@ -110,18 +109,20 @@ namespace TEAMModelOS.SDK.Module.AzureCosmosDBV3
             {
                 return true;
             }
-            else {
+            else
+            {
                 return false;
             }
         }
 
-        public static CosmosDbQuery GetSQL(Dictionary<string, object> dict, StringBuilder sql,string pk=null)
+        public static AzureCosmosQuery GetSQL(Dictionary<string, object> dict, StringBuilder sql, string pk = null)
         {
             if (dict != null)
             {
-                if (!DictIsNotNULL(dict)) {
+                if (!DictIsNotNULL(dict))
+                {
                     return null;
-                } 
+                }
                 Dictionary<string, object> parmeters = new Dictionary<string, object>();
 
                 int offsetNum = -1;
@@ -148,7 +149,7 @@ namespace TEAMModelOS.SDK.Module.AzureCosmosDBV3
 
                 //处理顺序
                 Stack<KeyValuePair<string, object>> stack = new Stack<KeyValuePair<string, object>>();
-                Dictionary<string, object> forGetParmeter = new Dictionary<string, object>(); 
+                Dictionary<string, object> forGetParmeter = new Dictionary<string, object>();
                 foreach (string item in dict.Keys)
                 {
                     if (item.EndsWith(".|"))
@@ -279,19 +280,21 @@ namespace TEAMModelOS.SDK.Module.AzureCosmosDBV3
                 {
                     sql.Append(" where 1=1 ").Append(WhereString);
                 }
-                else {
-                    sql.Append(" where c.pk='"+pk+"'").Append(WhereString);
+                else
+                {
+                    sql.Append(" where c.pk='" + pk + "'").Append(WhereString);
                 }
-                
+
 
                 if (ASC != null)
                 {
-                    sql.Append(" Order By c." + OrderByValue );
+                    sql.Append(" Order By c." + OrderByValue);
                     //sql.Append(" Order By c." + "@OrderByValue");
                 }
-                else if (DESC != null) {
+                else if (DESC != null)
+                {
                     sql.Append(" Order By c." + OrderByValue + " DESC ");
-                   // sql.Append(" Order By c." + "@OrderByValue"+ " DESC " );
+                    // sql.Append(" Order By c." + "@OrderByValue"+ " DESC " );
                 }
 
                 if (pageBool && offsetNum != -1 && limitNum != 0)
@@ -307,7 +310,7 @@ namespace TEAMModelOS.SDK.Module.AzureCosmosDBV3
                 parmeters = GetParmeter(forGetParmeter, parmeters, offsetNum, limitNum);
 
 
-                CosmosDbQuery cosmosDbQuery = new CosmosDbQuery
+                AzureCosmosQuery cosmosDbQuery = new AzureCosmosQuery
                 {
                     QueryText = sql.ToString(),
                     Parameters = parmeters
@@ -327,11 +330,13 @@ namespace TEAMModelOS.SDK.Module.AzureCosmosDBV3
             {
                 pageBool = true;
                 limitNum = int.Parse(limit.ToString());
-                if (limitNum < 0) {
+                if (limitNum < 0)
+                {
                     throw new BizException("PAGESIZE can't be less than 0 !");
                 }
                 offsetNum = (int.Parse(page.ToString()) - 1) * limitNum;
-                if (offsetNum < 0) {
+                if (offsetNum < 0)
+                {
                     throw new BizException("CURRPAGE can't be less than 1 !");
                 }
             }
@@ -416,7 +421,7 @@ namespace TEAMModelOS.SDK.Module.AzureCosmosDBV3
             }
             else if (value is JsonElement jsonElement)
             {
-                
+
                 if (jsonElement.ValueKind is JsonValueKind.Array)
                 {
                     keyListValueList = true;
@@ -429,7 +434,7 @@ namespace TEAMModelOS.SDK.Module.AzureCosmosDBV3
                 }
                 else
                 {
-                    if (compareOperNum != 4) keyListValueList = true; 
+                    if (compareOperNum != 4) keyListValueList = true;
                     return logicOper + key + compareOper + " @" + key1 + " ";
                 }
 
@@ -517,8 +522,8 @@ namespace TEAMModelOS.SDK.Module.AzureCosmosDBV3
             {
                 Type stype = value.GetType();
                 TypeCode typeCode = Type.GetTypeCode(stype);
-                
-                if(compareOperNum == 7) keyListValueList = true;
+
+                if (compareOperNum == 7) keyListValueList = true;
                 string sql = "";
                 if (value is string)
                 {
@@ -731,7 +736,7 @@ namespace TEAMModelOS.SDK.Module.AzureCosmosDBV3
             moreThan = 0, lessThan = 1, notMoreThan = 2, notLessThan = 3, equal = 4, notEqual = 5, like = 6, notLike = 7, IN = 8
         }
 
-        private static Dictionary<string, object> GetParmeter(Dictionary<string, object> dict, Dictionary<string, object> parmeters,int offset = 0,int limit = 0)
+        private static Dictionary<string, object> GetParmeter(Dictionary<string, object> dict, Dictionary<string, object> parmeters, int offset = 0, int limit = 0)
         {
             int i = 0;
             foreach (KeyValuePair<string, object> keyValue in dict)

+ 17 - 0
TEAMModelOS.SDK/DI/AzureRedis/AzureRedisExtensions.cs

@@ -0,0 +1,17 @@
+using Microsoft.Azure.Cosmos.Table;
+using Microsoft.Azure.Cosmos.Table.Queryable;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Linq;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public static class AzureRedisExtensions
+    {
+       
+    }
+}

+ 47 - 0
TEAMModelOS.SDK/DI/AzureRedis/AzureRedisFactory.cs

@@ -0,0 +1,47 @@
+
+using Microsoft.Azure.Cosmos.Table;
+using Microsoft.Extensions.Options;
+using Microsoft.Extensions.Logging;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.Extensions.DependencyInjection;
+using Azure.Storage.Blobs;
+using Azure.Storage.Blobs.Models;
+using Azure.Storage.Blobs.Specialized;
+using StackExchange.Redis;
+using System.Collections.Concurrent;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public class AzureRedisFactory
+    {
+        private readonly IServiceProvider _services;
+        private readonly IOptionsMonitor<AzureRedisFactoryOptions> _optionsMonitor;
+        private readonly ILogger _logger;
+        private ConcurrentDictionary<string, ConnectionMultiplexer> ConnectionMultiplexers { get; } = new ConcurrentDictionary<string, ConnectionMultiplexer>();
+        public AzureRedisFactory(IServiceProvider services, IOptionsMonitor<AzureRedisFactoryOptions> optionsMonitor, ILogger<AzureRedisFactory> logger)
+        {
+            if (services == null) throw new ArgumentNullException(nameof(services));
+            if (optionsMonitor == null) throw new ArgumentNullException(nameof(optionsMonitor));
+
+            _services = services;
+            _optionsMonitor = optionsMonitor;
+            _logger = logger;
+        }
+
+        public IDatabase GetRedisClient( int dbnum = -1,string name = "Default")
+        {           
+            try
+            {
+                var cm = ConnectionMultiplexers.GetOrAdd(name, x => ConnectionMultiplexer.Connect(_optionsMonitor.Get(name).RedisConnectionString));
+                return cm.GetDatabase(dbnum);
+            }
+            catch (OptionsValidationException e)
+            {
+                _logger?.LogWarning(e, e.Message);
+                return null;
+            }
+        }
+    }
+}

+ 22 - 0
TEAMModelOS.SDK/DI/AzureRedis/AzureRedisFactoryExtensions.cs

@@ -0,0 +1,22 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public static class AzureRedisFactoryExtensions
+    {
+        public static IServiceCollection AddAzureRedis(this IServiceCollection services, string connectionString, string name = "Default")
+        {
+            if (services == null) throw new ArgumentNullException(nameof(services));            
+            if (connectionString == null) throw new ArgumentNullException(nameof(connectionString));
+
+            services.TryAddSingleton<AzureRedisFactory>();
+            services.Configure<AzureRedisFactoryOptions>(name, o => { o.Name = name; o.RedisConnectionString = connectionString; });
+
+            return services;
+        }
+    }
+}

+ 14 - 0
TEAMModelOS.SDK/DI/AzureRedis/AzureRedisFactoryOptions.cs

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public class AzureRedisFactoryOptions
+    {
+        public string Name { get; set; }
+        public string RedisConnectionString { get; set; }
+    }
+
+   
+}

+ 105 - 0
TEAMModelOS.SDK/DI/AzureServiceBus/AzureServiceBusExtensions.cs

@@ -0,0 +1,105 @@
+using Microsoft.Azure.Cosmos.Table;
+using Microsoft.Azure.Cosmos.Table.Queryable;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Linq;
+using Azure.Messaging.ServiceBus;
+using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public static class AzureServiceBusExtensions
+    {
+
+        /// <summary>
+        /// 發送信息至對列或主題
+        /// </summary>       
+        /// <param name="pathName">QueueName or TopicName</param>
+        /// <param name="message">訊息</param>
+        /// <returns></returns>
+        public static async Task SendMessageAsync(this ServiceBusClient client, string pathName, string message)
+        {
+            try
+            {
+                ServiceBusSender sender = client.CreateSender(pathName);
+                await sender.SendMessageAsync(new ServiceBusMessage(Encoding.UTF8.GetBytes(message)));
+            }
+            catch
+            {
+                throw;
+            }
+        }
+
+        /// <summary>
+        /// 批量發送訊息至對列或主題,如果批量失敗返回False
+        /// </summary>       
+        /// <param name="pathName">QueueName or TopicName</param>
+        /// <param name="messages">批量訊息</param>
+        /// <returns></returns>
+        public static async Task<bool> SendBatchMessageAsync(this ServiceBusClient client, string pathName, IList<string> messages)
+        {
+            try
+            {
+                ServiceBusSender sender = client.CreateSender(pathName);
+                ServiceBusMessageBatch messageBatch = await sender.CreateMessageBatchAsync();
+                foreach (var msg in messages)
+                {
+                    if (!messageBatch.TryAddMessage(new ServiceBusMessage(Encoding.UTF8.GetBytes(msg)))) return false;
+                }
+                await sender.SendMessagesAsync(messageBatch);
+                return true;
+            }
+            catch
+            {
+                return false;
+            }
+        }
+
+        /// <summary>
+        /// 發送信息至對列或主題(指定時間排程)
+        /// </summary>       
+        /// <param name="pathName">QueueName or TopicName</param>
+        /// <param name="message">訊息</param>
+        /// <returns>排程訊息的序列號。</returns>
+        public static async Task<long> SendScheduleMessageAsync(this ServiceBusClient client, string pathName, string message, DateTimeOffset scheduleTime)
+        {
+            try
+            {
+                ServiceBusSender sender = client.CreateSender(pathName);
+                return await sender.ScheduleMessageAsync(new ServiceBusMessage(Encoding.UTF8.GetBytes(message)), scheduleTime);
+            }
+            catch
+            {
+                throw;
+            }
+        }
+
+        /// <summary>
+        /// 批量發送訊息至對列或主題(指定時間排程),如果批量失敗返回False
+        /// </summary>       
+        /// <param name="pathName">QueueName or TopicName</param>
+        /// <param name="messages">批量訊息</param>
+        /// <returns>排程訊息的序列號</returns>
+        public static async Task<long[]> SendScheduleMessagesAsync(this ServiceBusClient client, string pathName, IList<string> messages, DateTimeOffset scheduleTime)
+        {
+            try
+            {
+                ServiceBusSender sender = client.CreateSender(pathName);
+                List<ServiceBusMessage> msgs = new List<ServiceBusMessage>() { };
+                foreach (var msg in messages)
+                {
+                    msgs.Add(new ServiceBusMessage(Encoding.UTF8.GetBytes(msg)));
+                }
+                return await sender.ScheduleMessagesAsync(msgs, scheduleTime);
+            }
+            catch
+            {
+                return null;
+            }
+        }
+    }
+}

+ 48 - 0
TEAMModelOS.SDK/DI/AzureServiceBus/AzureServiceBusFactory.cs

@@ -0,0 +1,48 @@
+
+using Microsoft.Azure.Cosmos.Table;
+using Microsoft.Extensions.Options;
+using Microsoft.Extensions.Logging;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.Extensions.DependencyInjection;
+using Azure.Storage.Blobs;
+using Azure.Storage.Blobs.Models;
+using Azure.Storage.Blobs.Specialized;
+using StackExchange.Redis;
+using System.Collections.Concurrent;
+using Azure.Messaging.ServiceBus;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public class AzureServiceBusFactory
+    {
+        private readonly IServiceProvider _services;
+        private readonly IOptionsMonitor<AzureServiceBusFactoryOptions> _optionsMonitor;
+        private readonly ILogger _logger;
+        private ConcurrentDictionary<string, ServiceBusClient> ServiceBusClients { get; } = new ConcurrentDictionary<string, ServiceBusClient>();
+        public AzureServiceBusFactory(IServiceProvider services, IOptionsMonitor<AzureServiceBusFactoryOptions> optionsMonitor, ILogger<AzureServiceBusFactory> logger)
+        {
+            if (services == null) throw new ArgumentNullException(nameof(services));
+            if (optionsMonitor == null) throw new ArgumentNullException(nameof(optionsMonitor));
+
+            _services = services;
+            _optionsMonitor = optionsMonitor;
+            _logger = logger;            
+        }
+
+        public ServiceBusClient GetServiceBusClient(string name = "Default")
+        {           
+            try
+            {
+                var client = ServiceBusClients.GetOrAdd(name, x => new ServiceBusClient(_optionsMonitor.Get(name).ServiceBusConnectionString));               
+                return client;
+            }
+            catch (OptionsValidationException e)
+            {
+                _logger?.LogWarning(e, e.Message);
+                return null;
+            }
+        }       
+    }
+}

+ 22 - 0
TEAMModelOS.SDK/DI/AzureServiceBus/AzureServiceBusFactoryExtensions.cs

@@ -0,0 +1,22 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public static class AzureServiceBusFactoryExtensions
+    {
+        public static IServiceCollection AddAzureServiceBus(this IServiceCollection services, string connectionString, string name = "Default")
+        {
+            if (services == null) throw new ArgumentNullException(nameof(services));            
+            if (connectionString == null) throw new ArgumentNullException(nameof(connectionString));
+
+            services.TryAddSingleton<AzureServiceBusFactory>();
+            services.Configure<AzureServiceBusFactoryOptions>(name, o => { o.Name = name; o.ServiceBusConnectionString = connectionString; });
+
+            return services;
+        }
+    }
+}

+ 13 - 0
TEAMModelOS.SDK/DI/AzureServiceBus/AzureServiceBusFactoryOptions.cs

@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public class AzureServiceBusFactoryOptions
+    {
+        public string Name { get; set; }
+        public string ServiceBusConnectionString { get; set; }
+      
+    }
+}

+ 99 - 0
TEAMModelOS.SDK/DI/AzureStorage/AzureStorageBlobExtensions.cs

@@ -0,0 +1,99 @@
+using System.Threading.Tasks;
+using Azure.Storage;
+using Azure.Storage.Blobs;
+using Azure.Storage.Blobs.Models;
+using TEAMModelOS.SDK.Module.AzureBlob.Configuration;
+using TEAMModelOS.SDK.Module.AzureBlob.Container;
+using TEAMModelOS.SDK.Context.Constant;
+using TEAMModelOS.SDK.Helper.Security.ShaHash;
+using System;
+using System.IO;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public static class AzureStorageBlobExtensions
+    {
+        /// <summary>
+        /// 取得指定前置詞的 Blob 名稱的總大小(Bytes),例如指定目錄名稱為前置詞
+        /// </summary>      
+        /// <param name="prefix">篩選開頭名稱,Null代表容器總大小</param>
+        /// <returns>總大小(Bytes),如果為Null代表查無前置詞或者發生錯誤</returns>
+        public static async Task<long?> GetBlobsSize(this BlobContainerClient client, string prefix = null)
+        {
+            long? size = 0;
+            try
+            {                
+                await foreach (var item in client.GetBlobsAsync(BlobTraits.None, BlobStates.None, prefix))
+                {
+                    size += item.Properties.ContentLength;
+                };
+
+                return size;
+            }
+            catch 
+            {
+                return null;
+            }
+        }
+
+        /// <summary>
+        /// 系统管理员 资源,题目关联,htex关联,学习活动学生上传文件关联,基本信息关联,教室平面图关联,评测冷数据关联
+        /// "system": [ "res", "item", "htex", "task", "info", "room", "exam" ],
+        /// 资源,题目关联,htex关联,学习活动学生上传文件关联,基本信息关联,教室平面图关联,评测冷数据关联
+        /// "school": [ "res", "item", "htex", "task", "info", "room", "exam" ],
+        /// 资源,题目关联,htex关联,学习活动关联,教师基本信息关联
+        /// "teacher": [ "res", "item", "htex", "task", "info" ],
+        /// 答案及学习活动上传的文件,学生基本信息关联
+        ///"student": [ "stu/{studentId}/ans", "stu/{studentId}/task" ]
+        /// </summary>
+        /// <param name="name">容器名称</param>
+        /// <param name="text">文件内容的流</param>
+        /// <param name="folder">业务文件夹</param>
+        /// <param name="fileName">文件名</param>
+        /// <param name="contentTypeDefault">是否存放文件后缀对应的contentType</param>
+        /// <returns></returns>
+        public static async Task<AzureBlobModel> UploadFileByContainer(this AzureStorageFactory azureStorageFactory, string name, string text, string folder, string fileName, bool contentTypeDefault = true)
+        {
+
+            // string groupName =folder;
+
+            BlobContainerClient blobContainer =  azureStorageFactory.GetBlobContainerClient(name.ToLower().Replace("#", "")); //blobClient.GetContainerReference(groupName); 
+            Uri url = blobContainer.Uri;
+
+            var blockBlob = blobContainer.GetBlobClient(folder + "/" + fileName);
+            string fileext = fileName.Substring(fileName.LastIndexOf(".") > 0 ? fileName.LastIndexOf(".") : 0);
+            string content_type = "application/octet-stream";
+            if (!contentTypeDefault)
+            {
+                ContentTypeDict.dict.TryGetValue(fileext, out string contenttype);
+                if (!string.IsNullOrEmpty(contenttype))
+                {
+                    content_type = contenttype;
+                    
+                    
+                }
+                else
+                {
+                   
+                    //blockBlob.Properties.ContentType = content_type;
+                }
+            }
+            else
+            {
+               
+                //blockBlob.Properties.ContentType = content_type;
+            }
+            byte[] bytes = System.Text.Encoding.Default.GetBytes(text);
+            Stream streamBlob= new MemoryStream(bytes);
+            await blockBlob.UploadAsync(streamBlob,true);
+            blockBlob.SetHttpHeaders(new BlobHttpHeaders { ContentType = content_type });
+            AzureBlobModel model = new AzureBlobModel(fileName, name, folder, fileName, folder, content_type, bytes.Length)
+            {
+                Sha1Code = ShaHashHelper.GetSHA1(bytes),
+                BlobUrl = blockBlob.Uri.ToString()
+            };
+            return model;
+        }
+
+    }
+}

+ 350 - 0
TEAMModelOS.SDK/DI/AzureStorage/AzureStorageFactory.cs

@@ -0,0 +1,350 @@
+
+using Microsoft.Azure.Cosmos.Table;
+using Microsoft.Extensions.Options;
+using Microsoft.Extensions.Logging;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.Extensions.DependencyInjection;
+using Azure.Storage.Blobs;
+using Azure.Storage.Blobs.Models;
+using Azure.Storage.Blobs.Specialized;
+using Azure.Storage.Sas;
+using Azure.Storage;
+using TEAMModelOS.SDK.Extension;
+using Azure.Storage.Queues;
+using TEAMModelOS.SDK.Context.Attributes.Azure;
+using System.Threading.Tasks;
+using TEAMModelOS.SDK.Module.AzureBlob.Configuration;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public class AzureStorageFactory
+    {
+        private readonly IServiceProvider _services;
+        private readonly IOptionsMonitor<AzureStorageFactoryOptions> _optionsMonitor;
+        private readonly ILogger _logger;
+        public AzureStorageFactory(IServiceProvider services, IOptionsMonitor<AzureStorageFactoryOptions> optionsMonitor, ILogger<AzureStorageFactory> logger)
+        {
+            if (services == null) throw new ArgumentNullException(nameof(services));
+            if (optionsMonitor == null) throw new ArgumentNullException(nameof(optionsMonitor));
+
+            _services = services;
+            _optionsMonitor = optionsMonitor;
+            _logger = logger;
+        }
+
+        public BlobServiceClient GetBlobServiceClient(string name = "Default")
+        {            
+            try
+            {
+                var options = _optionsMonitor.Get(name);
+                return new BlobServiceClient(options.StorageAccountConnectionString);
+            }
+            catch (OptionsValidationException e)
+            {
+                _logger?.LogWarning(e, e.Message);
+                return null;
+            }
+
+        }
+
+        public BlobContainerClient GetBlobContainerClient(string containerName, string name = "Default")
+        {            
+            try
+            {
+                var options = _optionsMonitor.Get(name);
+                return new BlobContainerClient(options.StorageAccountConnectionString, containerName);
+            }
+            catch (OptionsValidationException e)
+            {
+                _logger?.LogWarning(e, e.Message);
+                return null;
+            }
+        }
+        
+        public BlobBatchClient GetBlobBatchClient(string name = "Default")
+        {           
+            try
+            {
+                var options = _optionsMonitor.Get(name);
+                BlobServiceClient blobServiceClient = new BlobServiceClient(options.StorageAccountConnectionString);
+                return blobServiceClient.GetBlobBatchClient();
+            }
+            catch (OptionsValidationException e)
+            {
+                _logger?.LogWarning(e, e.Message);
+                return null;
+            }
+        }
+
+        /// <summary>
+        /// 取得Blob Container SAS (有效期預設一天)
+        /// </summary>
+        /// <param name="containerName">容器名稱</param>        
+        /// <param name="blobContainerSasPermissions">權限(可多選)Flags</param>
+        /// <param name="name"></param>
+        /// <returns></returns>
+        public (string uri ,string sas) GetBlobContainerSAS(string containerName, BlobContainerSasPermissions blobContainerSasPermissions, string name = "Default")
+        {
+            try
+            {
+                var keys = Utils.ParseConnectionString(_optionsMonitor.Get(name).StorageAccountConnectionString);
+                var accountname = keys["AccountName"];
+                var accountkey = keys["AccountKey"];
+                var endpoint = keys["EndpointSuffix"];
+
+                var blobSasBuilder = new BlobSasBuilder
+                {
+                    StartsOn = DateTimeOffset.UtcNow.Subtract(new TimeSpan(0, 15, 0)),
+                    ExpiresOn = DateTimeOffset.UtcNow.Add(new TimeSpan(1, 0, 15, 0)),
+                    BlobContainerName = containerName
+                };
+
+                blobSasBuilder.SetPermissions(blobContainerSasPermissions);
+                var sskc = new StorageSharedKeyCredential(accountname, accountkey);
+                BlobSasQueryParameters sasQueryParameters = blobSasBuilder.ToSasQueryParameters(sskc);
+                UriBuilder fullUri = new UriBuilder()
+                {
+                    Scheme = "https",
+                    Host = $"{accountname}.blob.{endpoint}",
+                    Path = containerName
+                    //Query = sasQueryParameters.ToString()
+                };
+
+                return (fullUri.Uri.ToString(), sasQueryParameters.ToString());
+            }
+            catch
+            {
+                return (null, null);
+            }
+        }
+
+        /// <summary>
+        /// 取得Blob Container SAS (有效期預設一天)
+        /// </summary>
+        /// <param name="containerName">容器名稱</param>
+        /// <param name="blobName"></param>
+        /// <param name="blobContainerSasPermissions"></param>
+        /// <param name="name"></param>
+        /// <returns></returns>
+        public BlobAuth GetContainerSasUri(BlobSas blobSas, bool isRead, string name = "Default")
+        {
+            try
+            {
+                string containerName = null;
+                var keys = Utils.ParseConnectionString(_optionsMonitor.Get(name).StorageAccountConnectionString);
+                var accountname = keys["AccountName"];
+                var accountkey = keys["AccountKey"];
+                var endpoint = keys["EndpointSuffix"];
+                if (blobSas.role == "system")
+                {
+                    containerName = "teammodelos";
+                }
+                else
+                {
+                    containerName = blobSas.name.ToLower().Replace("#", "");
+                }
+                DateTimeOffset dateTime = DateTimeOffset.UtcNow.Add(new TimeSpan(1, 0, 15, 0));
+                long time = dateTime.ToUnixTimeMilliseconds();
+                var blobSasBuilder = new BlobSasBuilder
+                {
+                    StartsOn = DateTimeOffset.UtcNow.Subtract(new TimeSpan(0, 15, 0)),
+                    ExpiresOn = dateTime,
+                    BlobContainerName = containerName
+                };
+                BlobContainerSasPermissions blobContainerSasPermissions = BlobContainerSasPermissions.Read;
+                if (isRead) {
+                    blobContainerSasPermissions = BlobContainerSasPermissions.Read;
+                }
+                else {
+                    blobContainerSasPermissions = BlobContainerSasPermissions.Write | BlobContainerSasPermissions.Create | BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List;
+                }
+                blobSasBuilder.SetPermissions(blobContainerSasPermissions);
+                var sskc = new StorageSharedKeyCredential(accountname, accountkey);
+                BlobSasQueryParameters sasQueryParameters = blobSasBuilder.ToSasQueryParameters(sskc);
+                UriBuilder fullUri = new UriBuilder()
+                {
+                    Scheme = "https",
+                    Host = $"{accountname}.blob.{endpoint}",
+                    Path = containerName
+                    //Query = sasQueryParameters.ToString()
+                };
+                return new BlobAuth { url = fullUri.Uri.ToString(), sas = sasQueryParameters.ToString(), timeout = time, name = containerName };
+               // return (fullUri.Uri.ToString(), sasQueryParameters.ToString());
+            }
+            catch
+            {
+                return   null ;
+            }
+        }
+
+        /// <summary>
+        /// 取得Blob SAS (有效期預設一天)
+        /// </summary>
+        /// <param name="containerName">容器名稱</param>
+        /// <param name="blobName"></param>
+        /// <param name="blobSasPermissions">權限(可多選)Flags</param>
+        /// <param name="name"></param>
+        /// <returns></returns>
+        public string GetBlobSAS(string containerName, string blobName, BlobSasPermissions blobSasPermissions, string name = "Default")
+        {
+            try
+            {
+                var keys = Utils.ParseConnectionString(_optionsMonitor.Get(name).StorageAccountConnectionString);
+                var accountname = keys["AccountName"];
+                var accountkey = keys["AccountKey"];
+                var endpoint = keys["EndpointSuffix"];
+
+                var blobSasBuilder = new BlobSasBuilder
+                {
+                    StartsOn = DateTimeOffset.UtcNow.Subtract(new TimeSpan(0, 15, 0)),
+                    ExpiresOn = DateTimeOffset.UtcNow.Add(new TimeSpan(1, 0, 15, 0)),
+                    BlobContainerName = containerName,
+                    BlobName = blobName
+                };
+
+                blobSasBuilder.SetPermissions(blobSasPermissions);
+                var sskc = new StorageSharedKeyCredential(accountname, accountkey);
+                BlobSasQueryParameters sasQueryParameters = blobSasBuilder.ToSasQueryParameters(sskc);
+                UriBuilder fullUri = new UriBuilder()
+                {
+                    Scheme = "https",
+                    Host = $"{accountname}.blob.{endpoint}",
+                    Path = $"{containerName}/{blobName}",
+                    Query = sasQueryParameters.ToString()
+                };
+
+                return fullUri.Uri.ToString();
+            }
+            catch
+            {
+                return null;
+            }
+        }
+
+
+        /// <summary>
+        /// 取得Blob SAS (有效期預設一天)
+        /// </summary>
+        /// <param name="containerName">容器名稱</param>
+        /// <param name="blobName"></param>
+        /// <param name="blobSasPermissions"></param>
+        /// <param name="name"></param>
+        /// <returns></returns>
+        public BlobAuth GetBlobSasUriRead(string containerName, string blobName,string name = "Default")
+        {
+            try
+            {
+                var keys = Utils.ParseConnectionString(_optionsMonitor.Get(name).StorageAccountConnectionString);
+                var accountname = keys["AccountName"];
+                var accountkey = keys["AccountKey"];
+                var endpoint = keys["EndpointSuffix"];
+                DateTimeOffset dateTime = DateTimeOffset.UtcNow.Add(new TimeSpan(1, 0, 15, 0));
+                long time = dateTime.ToUnixTimeMilliseconds();
+                var blobSasBuilder = new BlobSasBuilder
+                {
+                    StartsOn = DateTimeOffset.UtcNow.Subtract(new TimeSpan(0, 15, 0)),
+                    ExpiresOn = dateTime,
+                    BlobContainerName = containerName,
+                    BlobName = blobName
+                };
+
+                blobSasBuilder.SetPermissions(BlobSasPermissions.Read);
+                var sskc = new StorageSharedKeyCredential(accountname, accountkey);
+                BlobSasQueryParameters sasQueryParameters = blobSasBuilder.ToSasQueryParameters(sskc);
+                UriBuilder fullUri = new UriBuilder()
+                {
+                    Scheme = "https",
+                    Host = $"{accountname}.blob.{endpoint}",
+                    Path = $"{containerName}/{blobName}",
+                    Query = sasQueryParameters.ToString()
+                };
+                return new BlobAuth { url = fullUri.Uri.ToString(), sas = sasQueryParameters.ToString(), timeout = time };
+               // return fullUri.Uri.ToString();
+            }
+            catch
+            {
+                return null;
+            }
+        }
+
+        public CloudTableClient GetCloudTableClient(string name = "Default")
+        {            
+            try
+            {
+                var options = _optionsMonitor.Get(name);
+                CloudStorageAccount storageAccount = CloudStorageAccount.Parse(options.StorageAccountConnectionString);
+                return storageAccount.CreateCloudTableClient();
+            }
+            catch (OptionsValidationException e)
+            {
+                _logger?.LogWarning(e, e.Message);
+                return null;
+            }
+        }
+
+       
+
+        /// <summary>
+        /// 可讓您管理儲存體帳戶中的所有佇列
+        /// </summary>
+        /// <param name="name"></param>
+        /// <returns></returns>
+        public QueueServiceClient GetQueueServiceClient(string name = "Default")
+        {            
+            try
+            {
+                var options = _optionsMonitor.Get(name);
+                return new QueueServiceClient(options.StorageAccountConnectionString);
+            }
+            catch (OptionsValidationException e)
+            {
+                _logger?.LogWarning(e, e.Message);
+                return null;
+            }
+        }
+
+        /// <summary>
+        /// 可讓您管理和操作個別佇列及其訊息
+        /// </summary>
+        /// <param name="name"></param>
+        /// <param name="queueName"></param>
+        /// <returns></returns>
+        public QueueClient GetQueueClient(string queueName, string name = "Default")
+        {
+            if (name == null) throw new ArgumentNullException(nameof(name));
+            try
+            {
+                var options = _optionsMonitor.Get(name);
+                return new QueueClient(options.StorageAccountConnectionString, queueName);
+            }
+            catch (OptionsValidationException e)
+            {
+                _logger?.LogWarning(e, e.Message);
+                return null;
+            }
+        }
+        public  async Task<CloudTable> InitializeTable<T>()
+        {
+            string TableName = GetTableSpace<T>();
+            CloudTable cloudTable = GetCloudTableClient().GetTableReference(TableName);
+            await cloudTable.CreateIfNotExistsAsync();
+            return cloudTable;
+        }
+        private string GetTableSpace<T>()
+        {
+            Type type = typeof(T);
+            string Name = type.Name;
+            object[] attributes = type.GetCustomAttributes(true);
+            foreach (object attribute in attributes) //2.通过映射,找到成员属性上关联的特性类实例,
+            {
+                if (attribute is TableNameAttribute tableSpace)
+                {
+                    Name = tableSpace.Name;
+                }
+            }
+            return Name;
+        }
+    }
+}

+ 22 - 0
TEAMModelOS.SDK/DI/AzureStorage/AzureStorageFactoryExtensions.cs

@@ -0,0 +1,22 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public static class AzureStorageFactoryExtensions
+    {
+        public static IServiceCollection AddAzureStorage(this IServiceCollection services, string connectionString,string name = "Default")
+        {
+            if (services == null) throw new ArgumentNullException(nameof(services));            
+            if (connectionString == null) throw new ArgumentNullException(nameof(connectionString));
+
+            services.TryAddSingleton<AzureStorageFactory>();
+            services.Configure<AzureStorageFactoryOptions>(name, o => { o.Name = name; o.StorageAccountConnectionString = connectionString; });
+
+            return services;
+        }
+    }
+}

+ 14 - 0
TEAMModelOS.SDK/DI/AzureStorage/AzureStorageFactoryOptions.cs

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public class AzureStorageFactoryOptions
+    {
+        public string Name { get; set; }
+        public string StorageAccountConnectionString { get; set; }
+    }
+
+   
+}

+ 516 - 0
TEAMModelOS.SDK/DI/AzureStorage/AzureStorageTableExtensions.cs

@@ -0,0 +1,516 @@
+using Microsoft.Azure.Cosmos.Table;
+using Microsoft.Azure.Cosmos.Table.Queryable;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Linq;
+using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
+using System.Reflection;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public static class AzureStorageTableExtensions
+    {
+ 
+        #region CloudTable 批次操作    
+
+        /// <summary>
+        /// 批次新增資料至Table儲存區。
+        /// </summary>
+        /// <param name="entities">欲快取的集合</param>
+        /// <returns></returns>
+        public static async Task<TableBatchResult> BatchInsertAsync<T>(this CloudTable table, IEnumerable<T> entities) where T : ITableEntity, new()
+        {
+            TableBatchOperation batchOperation = new TableBatchOperation();
+            foreach (var cache in entities)
+            {
+                batchOperation.Insert(cache);
+            }
+
+            return await table.ExecuteBatchAsync(batchOperation);
+        }
+
+        #endregion
+
+        #region CloudTable Get
+
+        /// <summary>
+        /// (同步)取得 table 中指定 PartitionKey 的所有集合。
+        /// </summary>
+        /// <returns></returns>
+        public static IEnumerable<T> Get<T>(this CloudTable table, string partitionKey) where T : ITableEntity, new()
+        {
+            TableQuery<T> query = new TableQuery<T>().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partitionKey));
+            return table.ExecuteQuery(query);
+        }
+
+        /// <summary>
+        /// (同步)取得指定 PartitionKey與 RowKey 的數據,效能:點查詢,最佳。
+        /// </summary>
+        /// <typeparam name="T">T</typeparam>       
+        /// <param name="partitionKey">PartitionKey</param>   
+        /// <param name="rowKey">RowKey</param>  
+        /// <returns></returns>
+        public static T Get<T>(this CloudTable table, string partitionKey, string rowKey) where T : ITableEntity, new()
+        {
+            TableOperation retrieveOperation = TableOperation.Retrieve<T>(partitionKey, rowKey);
+            var retrieveResult = table.Execute(retrieveOperation);
+            if (retrieveResult.Result != null)
+            {
+                //DynamicTableEntityJsonSeria1lizer
+                return (T)retrieveResult.Result;
+            }
+            else
+            {
+                return default(T);
+            }
+        }
+
+        public static DynamicTableEntity Get(this CloudTable table, string partitionKey, string rowKey)
+        {
+            TableOperation retrieveOperation = TableOperation.Retrieve(partitionKey, rowKey);
+            var retrieveResult = table.Execute(retrieveOperation);
+            if (retrieveResult.Result != null)
+            {
+                return retrieveResult.Result as DynamicTableEntity;
+            }
+            else
+            {
+                return null;
+            }
+        }
+
+        /// <summary>
+        /// 取得指定 PartitionKey 的所有集合(分頁),效能:範圍查詢,次佳。
+        /// </summary>
+        /// <typeparam name="T">T</typeparam>       
+        /// <param name="partitionKey">PartitionKey</param>
+        /// <param name="takeCount">指定每次返回數量</param>
+        /// <param name="specifyPropertys">指定只須返回的屬性,效能:伺服器端預測,降低延遲和成本</param>
+        /// <param name="onProgress">要返回集合的委派</param>
+        /// <param name="ct">CancellationToken</param>
+        /// <returns></returns>
+        public static async Task GetAsync<T>(this CloudTable table, string partitionKey, int? takeCount = null, List<string> specifyPropertys = null, Action<IList<T>> onProgress = null, CancellationToken ct = default(CancellationToken)) where T : ITableEntity, new()
+        {
+            TableQuery<T> tableQuery = null;
+            TableContinuationToken token = null;
+            var filter = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partitionKey);
+
+            if (specifyPropertys != null)
+                tableQuery = new TableQuery<T>().Where(filter).Select(specifyPropertys);
+            else
+                tableQuery = new TableQuery<T>().Where(filter);
+
+            if (takeCount != null) tableQuery.TakeCount = takeCount;
+
+            do
+            {
+                var queryResponse = await table.ExecuteQuerySegmentedAsync(tableQuery, token);
+                token = queryResponse.ContinuationToken;
+                onProgress?.Invoke(queryResponse.Results);
+            } while (token != null && !ct.IsCancellationRequested);
+        }
+
+        /// <summary>
+        /// 取得指定 PartitionKey 的所有集合,效能:範圍查詢,次佳。
+        /// </summary>
+        /// <typeparam name="T">T</typeparam>       
+        /// <param name="partitionKey">PartitionKey</param>
+        /// <param name="takeCount">指定每次返回數量</param>
+        /// <param name="specifyPropertys">指定只須返回的屬性,效能:伺服器端預測,降低延遲和成本</param>
+        /// <param name="onProgress">要返回集合的委派</param>
+        /// <param name="ct">CancellationToken</param>
+        /// <returns></returns>
+        public static async Task<IEnumerable<T>> GetAsync<T>(this CloudTable table, string partitionKey, int? takeCount = null, List<string> specifyPropertys = null, CancellationToken ct = default(CancellationToken)) where T : ITableEntity, new()
+        {
+            TableQuery<T> tableQuery = null;
+            TableContinuationToken token = null;
+            var filter = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partitionKey);
+
+            if (specifyPropertys != null)
+                tableQuery = new TableQuery<T>().Where(filter).Select(specifyPropertys);
+            else
+                tableQuery = new TableQuery<T>().Where(filter);
+
+            if (takeCount != null) tableQuery.TakeCount = takeCount;
+            var items = new List<T>();
+
+            do
+            {
+                var queryResponse = await table.ExecuteQuerySegmentedAsync(tableQuery, token);
+                token = queryResponse.ContinuationToken;
+                items.AddRange(queryResponse.Results);
+            } while (token != null && !ct.IsCancellationRequested);
+            return items;
+        }
+
+        /// <summary>
+        /// 傳回指定partitionKey的Count數量
+        /// </summary>        
+        /// <param name="partitionKey"></param>
+        /// <returns></returns>
+        public static int GetCount(this CloudTable table, string partitionKey)
+        {           
+
+            TableQuery query = new TableQuery().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partitionKey)).Select(new List<string> { "PartitionKey" });
+            var queryResponse = table.ExecuteQuery(query).ToList();
+            return queryResponse.Count();
+        }
+
+        #endregion
+
+        #region CloudTable Get All
+        /// <summary>
+        /// (同步)取得 table 的所有集合,效能:資料表掃描,不佳。
+        /// </summary>
+        /// <returns></returns>
+        public static IEnumerable<T> GetAll<T>(this CloudTable table) where T : ITableEntity, new()
+        {
+            return table.ExecuteQuery(new TableQuery<T>());
+        }
+
+        /// <summary>
+        /// 取得 table 的所有集合(分頁),效能:資料表掃描,不佳。
+        /// </summary>
+        /// <param name="takeCount">指定每次返回數量</param>
+        /// <param name="specifyPropertys">指定只須返回的屬性,效能:伺服器端預測,降低延遲和成本</param>
+        /// <param name="onProgress">要返回集合的委派</param>
+        /// <returns></returns>        
+        public static async Task GetAllAsync<T>(this CloudTable table, int? takeCount = null, List<string> specifyPropertys = null, Action<IList<T>> onProgress = null, CancellationToken ct = default(CancellationToken)) where T : ITableEntity, new()
+        {
+            TableContinuationToken token = null;
+            TableQuery<T> tableQuery = new TableQuery<T>();
+            if (specifyPropertys != null)
+                tableQuery = new TableQuery<T>().Select(specifyPropertys);
+            else
+                tableQuery = new TableQuery<T>();
+            if (takeCount != null) tableQuery.TakeCount = takeCount;
+            var items = new List<T>();
+
+            do
+            {
+                var queryResponse = await table.ExecuteQuerySegmentedAsync(tableQuery, token);
+                token = queryResponse.ContinuationToken;
+                items.AddRange(queryResponse.Results);
+                onProgress?.Invoke(queryResponse.Results);
+            } while (token != null && !ct.IsCancellationRequested);
+        }
+
+        /// <summary>
+        /// 取得 table 的所有集合,效能:資料表掃描,不佳。
+        /// </summary>
+        /// <param name="takeCount">指定每次返回數量</param>
+        /// <param name="specifyPropertys">指定只須返回的屬性,效能:伺服器端預測,降低延遲和成本</param>       
+        /// <returns></returns>        
+        public static async Task<IEnumerable<T>> GetAllAsync<T>(this CloudTable table, int? takeCount = null, List<string> specifyPropertys = null, CancellationToken ct = default(CancellationToken)) where T : ITableEntity, new()
+        {
+            TableContinuationToken token = null;
+            TableQuery<T> tableQuery = new TableQuery<T>();
+            if (takeCount != null) tableQuery.TakeCount = takeCount;
+            if (specifyPropertys != null)
+                tableQuery = new TableQuery<T>().Select(specifyPropertys);
+            else
+                tableQuery = new TableQuery<T>();
+            var items = new List<T>();
+
+            do
+            {
+                var queryResponse = await table.ExecuteQuerySegmentedAsync(tableQuery, token);
+                token = queryResponse.ContinuationToken;
+                items.AddRange(queryResponse.Results);
+            } while (token != null && !ct.IsCancellationRequested);
+            return items;
+        }
+        #endregion
+
+        public static async Task<T> Save<T>(this AzureStorageFactory azureStorageFactory, TableEntity entity) where T : TableEntity, new()
+        {
+            CloudTable TableName = await azureStorageFactory.InitializeTable<T>();
+            TableOperation operation = TableOperation.Insert(entity);
+            TableResult result = await TableName.ExecuteAsync(operation);
+            return (T)result.Result;
+        }
+        public static async Task<T> SaveOrUpdate<T>(this AzureStorageFactory azureStorageFactory, TableEntity entity) where T : TableEntity, new()
+        {
+            CloudTable TableName = await azureStorageFactory.InitializeTable<T>();
+            TableOperation operation = TableOperation.InsertOrReplace(entity);
+            TableResult result = await TableName.ExecuteAsync(operation);
+            return (T)result.Result;
+        }
+
+        public static async Task<T> Update<T>(this AzureStorageFactory azureStorageFactory, TableEntity entity) where T : TableEntity, new()
+        {
+            CloudTable TableName = await azureStorageFactory.InitializeTable<T>();
+            TableOperation operation = TableOperation.Replace(entity);
+            TableResult result = await TableName.ExecuteAsync(operation);
+            return (T)result.Result;
+        }
+
+        public static async Task<T> Delete<T>(this AzureStorageFactory azureStorageFactory, TableEntity entity) where T : TableEntity, new()
+        {
+            CloudTable TableName = await azureStorageFactory.InitializeTable<T>();
+            TableOperation operation = TableOperation.Delete(entity);
+            TableResult result = await TableName.ExecuteAsync(operation);
+            return (T)result.Result;
+        }
+
+        public static async Task<List<T>> DeleteAll<T>(this AzureStorageFactory azureStorageFactory,  List<T> entitys) where T : TableEntity, new()
+        {
+            if (entitys.IsEmpty())
+            {
+                return null;
+            }
+            CloudTable TableName = await azureStorageFactory.InitializeTable<T>();
+            IList<Dictionary<string, List<T>>> listInfo = new List<Dictionary<string, List<T>>>();
+            foreach (IGrouping<string, T> group in entitys.GroupBy(c => c.PartitionKey))
+            {
+                Dictionary<string, List<T>> dictInfo = new Dictionary<string, List<T>>
+                {
+                    { group.Key, group.ToList() }
+                };
+                listInfo.Add(dictInfo);
+            }
+
+            foreach (Dictionary<string, List<T>> dict in listInfo)
+            {
+                IList<TableResult> result = null;
+                foreach (string key in dict.Keys)
+                {
+                    List<T> values = dict[key];
+                     
+                    int pageSize = 100;
+                    int pages = (int)Math.Ceiling((double)values.Count / pageSize);
+                    for (int i = 0; i < pages; i++)
+                    {
+                        List<T> lists = values.Skip((i) * pageSize).Take(pageSize).ToList();
+                        TableBatchOperation batchOperation = new TableBatchOperation();
+                        for (int j = 0; j < lists.Count; j++)
+                        {
+                            batchOperation.Delete(lists[j]);
+                        }
+                        result = await TableName.ExecuteBatchAsync(batchOperation);
+                    }
+                }
+            }
+            return entitys;
+        }
+
+        public static async Task<List<T>> SaveOrUpdateAll<T>(this AzureStorageFactory azureStorageFactory, List<T> entitys) where T : TableEntity, new()
+        {
+            if (entitys.IsEmpty())
+            {
+                return null;
+            }
+            CloudTable TableName = await azureStorageFactory.InitializeTable<T>();
+            IList<Dictionary<string, List<T>>> listInfo = new List<Dictionary<string, List<T>>>();
+            foreach (IGrouping<string, T> group in entitys.GroupBy(c => c.PartitionKey))
+            {
+                Dictionary<string, List<T>> dictInfo = new Dictionary<string, List<T>>
+                {
+                    { group.Key, group.ToList() }
+                };
+                listInfo.Add(dictInfo);
+            }
+
+            foreach (Dictionary<string, List<T>> dict in listInfo)
+            {
+                IList<TableResult> result = null;
+                foreach (string key in dict.Keys)
+                {
+                    List<T> values = dict[key];
+
+                    int pageSize = 100;
+                    int pages = (int)Math.Ceiling((double)values.Count / pageSize);
+                    for (int i = 0; i < pages; i++)
+                    {
+                        List<T> lists = values.Skip((i) * pageSize).Take(pageSize).ToList();
+                        TableBatchOperation batchOperation = new TableBatchOperation();
+                        for (int j = 0; j < lists.Count; j++)
+                        {
+                            batchOperation.InsertOrReplace(lists[j]);
+                        }
+                        result = await TableName.ExecuteBatchAsync(batchOperation);
+                    }
+                }
+            }
+            return entitys;
+        }
+        public static async Task<List<T>> UpdateAll<T>(this AzureStorageFactory azureStorageFactory, List<T> entitys) where T : TableEntity, new()
+        {
+            if (entitys.IsEmpty())
+            {
+                return null;
+            }
+            CloudTable TableName = await azureStorageFactory.InitializeTable<T>();
+            IList<Dictionary<string, List<T>>> listInfo = new List<Dictionary<string, List<T>>>();
+            foreach (IGrouping<string, T> group in entitys.GroupBy(c => c.PartitionKey))
+            {
+                Dictionary<string, List<T>> dictInfo = new Dictionary<string, List<T>>
+                {
+                    { group.Key, group.ToList() }
+                };
+                listInfo.Add(dictInfo);
+            }
+
+            foreach (Dictionary<string, List<T>> dict in listInfo)
+            {
+                IList<TableResult> result = null;
+                foreach (string key in dict.Keys)
+                {
+                    List<T> values = dict[key];
+                  
+                    int pageSize = 100;
+                    int pages = (int)Math.Ceiling((double)values.Count / pageSize);
+                    for (int i = 0; i < pages; i++)
+                    {
+                        List<T> lists = values.Skip((i) * pageSize).Take(pageSize).ToList();
+                        TableBatchOperation batchOperation = new TableBatchOperation();
+                        for (int j = 0; j < lists.Count; j++)
+                        {
+                            batchOperation.Replace(lists[j]);
+                        }
+                        result = await TableName.ExecuteBatchAsync(batchOperation);
+                    }
+                }
+            }
+            return entitys;
+        }
+        public static async Task<List<T>> SaveAll<T>(this AzureStorageFactory azureStorageFactory, List<T> entitys) where T : TableEntity, new()
+        {
+            if (entitys.IsEmpty())
+            {
+                return null;
+            }
+            CloudTable TableName = await azureStorageFactory.InitializeTable<T>();
+            IList<Dictionary<string, List<T>>> listInfo = new List<Dictionary<string, List<T>>>();
+            foreach (IGrouping<string, T> group in entitys.GroupBy(c => c.PartitionKey))
+            {
+                Dictionary<string, List<T>> dictInfo = new Dictionary<string, List<T>>
+                {
+                    { group.Key, group.ToList() }
+                };
+                listInfo.Add(dictInfo);
+            }
+
+            foreach (Dictionary<string, List<T>> dict in listInfo)
+            {
+                IList<TableResult> result = null;
+                foreach (string key in dict.Keys)
+                {
+                    List<T> values = dict[key];
+                  
+                    int pageSize = 100;
+                    int pages = (int)Math.Ceiling((double)values.Count / pageSize);
+                    for (int i = 0; i < pages; i++)
+                    {
+                        List<T> lists = values.Skip((i) * pageSize).Take(pageSize).ToList();
+                        TableBatchOperation batchOperation = new TableBatchOperation();
+                        for (int j = 0; j < lists.Count; j++)
+                        {
+                            batchOperation.Insert(lists[j]);
+                        }
+                        result = await TableName.ExecuteBatchAsync(batchOperation);
+                    }
+                }
+            }
+            return entitys;
+        }
+
+        public static async Task<List<T>> FindListByDict<T>(this AzureStorageFactory azureStorageFactory, Dictionary<string, object> dict) where T : TableEntity, new()
+        {
+            CloudTable TableName = await azureStorageFactory.InitializeTable<T>();
+            var exQuery = new TableQuery<T>();
+            StringBuilder builder = new StringBuilder();
+            if (null != dict && dict.Count > 0)
+            {
+                var keys = dict.Keys;
+                int index = 1;
+                foreach (string key in keys)
+                {
+                    if (dict[key] != null && !string.IsNullOrEmpty(dict[key].ToString()))
+                    {
+                        string typeStr = SwitchType<T>(dict[key], key);
+                        if (string.IsNullOrEmpty(typeStr))
+                        {
+                            continue;
+                        }
+                        if (index == 1)
+                        {
+                            //builder.Append(TableQuery.GenerateFilterCondition(key, QueryComparisons.Equal, dict[key].ToString()));
+                            builder.Append(typeStr);
+
+                        }
+                        else
+                        {
+                            //builder.Append("  " + TableOperators.And + "  " + TableQuery.GenerateFilterCondition(key, QueryComparisons.Equal, dict[key].ToString()));
+                            builder.Append("  " + TableOperators.And + "  " + typeStr);
+
+                        }
+                        index++;
+                    }
+                    else
+                    {
+                        throw new Exception("The parameter must have value!");
+                    }
+                }
+
+                exQuery.Where(builder.ToString());
+                return await QueryList<T>(exQuery, TableName);
+            }
+            else
+            {
+                return null;
+            }
+        }
+
+
+
+        private static async Task<List<T>> QueryList<T>(TableQuery<T> exQuery, CloudTable TableName  ) where T : TableEntity, new()
+        {
+            TableContinuationToken continuationToken = null;
+            List<T> entitys = new List<T>();
+            do
+            {
+                var result = await TableName.ExecuteQuerySegmentedAsync(exQuery, continuationToken);
+                if (result.Results.Count > 0)
+                {
+                    entitys.AddRange(result.ToList());
+                }
+                continuationToken = result.ContinuationToken;
+            } while (continuationToken != null);
+            return entitys;
+        }
+
+        private static string SwitchType<T>(object obj, string key)
+        {
+            Type objType = typeof(T);
+            PropertyInfo property = objType.GetProperty(key);
+
+            //Type s = obj.GetType();
+            //TypeCode typeCode = Type.GetTypeCode(s);
+            if (property == null)
+            {
+                //return null;
+                throw new Exception(objType.FullName + " PropertyInfo doesn't include this parameter :" + key);
+            }
+            TypeCode typeCode = Type.GetTypeCode(property.PropertyType);
+
+
+            switch (typeCode)
+            {
+
+                case TypeCode.String: return TableQuery.GenerateFilterCondition(key, QueryComparisons.Equal, obj.ToString());
+                case TypeCode.Int32: return TableQuery.GenerateFilterConditionForInt(key, QueryComparisons.Equal, int.Parse(obj.ToString()));
+                case TypeCode.Double: return TableQuery.GenerateFilterConditionForDouble(key, QueryComparisons.Equal, (double)obj);
+                case TypeCode.Byte: return TableQuery.GenerateFilterConditionForBinary(key, QueryComparisons.Equal, (byte[])obj);
+                case TypeCode.Boolean: return TableQuery.GenerateFilterConditionForBool(key, QueryComparisons.Equal, (bool)obj);
+                case TypeCode.DateTime: return TableQuery.GenerateFilterConditionForDate(key, QueryComparisons.Equal, (DateTimeOffset)obj);
+                case TypeCode.Int64: return TableQuery.GenerateFilterConditionForLong(key, QueryComparisons.Equal, long.Parse(obj.ToString()));
+                default: return null;
+            }
+        }
+    }
+}

+ 7 - 7
TEAMModelOS.SDK/Module/AzureBlob/Container/AzureBlobModel.cs

@@ -1,4 +1,4 @@
-
+
 using Microsoft.AspNetCore.Http;
 using Microsoft.Azure.Cosmos.Table;
 using System;
@@ -8,7 +8,7 @@ using TEAMModelOS.SDK.Helper.Common.DateTimeHelper;
 
 namespace TEAMModelOS.SDK.Module.AzureBlob.Container
 {
-    
+
     public class AzureBlobModel : TableEntity
     {
 
@@ -19,14 +19,14 @@ namespace TEAMModelOS.SDK.Module.AzureBlob.Container
             Timestamp = DateTime.UtcNow;
         }
 
-        public AzureBlobModel(IFormFile f, string Container ,string groupName ,string newName)
+        public AzureBlobModel(IFormFile f, string Container, string groupName, string newName)
         {
             long time = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
             ContentType = f.ContentType;
             ContentDisposition = f.ContentDisposition;
             FileName = f.FileName;
             // Headers = f.Headers.Values;
-            RealName =  groupName + "/"+ newName;
+            RealName = groupName + "/" + newName;
             Folder = groupName;
             Length = f.Length;
             Name = f.Name;
@@ -37,7 +37,7 @@ namespace TEAMModelOS.SDK.Module.AzureBlob.Container
             Timestamp = DateTimeHelper.ConvertToDateTime(time);
         }
 
-        public AzureBlobModel(FileInfo f, string Container, string groupName, string newName ,string  contentType)
+        public AzureBlobModel(FileInfo f, string Container, string groupName, string newName, string contentType)
         {
             long time = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
             ContentType = contentType;
@@ -55,7 +55,7 @@ namespace TEAMModelOS.SDK.Module.AzureBlob.Container
             Timestamp = DateTimeHelper.ConvertToDateTime(time);
         }
 
-        public AzureBlobModel(string fileName, string Container, string groupName, string newName, string contentType ,long length)
+        public AzureBlobModel(string fileName, string Container, string groupName, string newName, string contentType, long length)
         {
             long time = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
             ContentType = contentType;
@@ -72,7 +72,7 @@ namespace TEAMModelOS.SDK.Module.AzureBlob.Container
             Extension = fileName.Substring(fileName.LastIndexOf(".") + 1, (fileName.Length - fileName.LastIndexOf(".") - 1)); //扩展名
             Timestamp = DateTimeHelper.ConvertToDateTime(time);
         }
-        public AzureBlobModel(string fileName, string Container, string groupName, string newName,string sha1Code, string contentType, long length)
+        public AzureBlobModel(string fileName, string Container, string groupName, string newName, string sha1Code, string contentType, long length)
         {
             long time = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
             ContentType = contentType;

+ 14 - 0
TEAMModelOS.SDK/DI/AzureStorage/Inner/BlobAuth.cs

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.Module.AzureBlob.Configuration
+{
+    public class BlobAuth
+    {
+        public string url { get; set; }
+        public string sas { get; set; }
+        public long timeout { get; set; }
+        public string name { get; set; }
+    }
+}

+ 2 - 2
TEAMModelOS.SDK/Module/AzureBlob/Configuration/BlobSas.cs

@@ -1,4 +1,4 @@
-using System;
+using System;
 using System.Collections.Generic;
 using System.ComponentModel.DataAnnotations;
 using System.Text;
@@ -20,7 +20,7 @@ namespace TEAMModelOS.SDK.Module.AzureBlob.Configuration
         /// <summary>
         ///如果是学生则有值
         /// </summary>
-       
+
         public string code { get; set; }
     }
 }

+ 114 - 0
TEAMModelOS.SDK/DI/DingDing/DingDing.cs

@@ -0,0 +1,114 @@
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Net.Http;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using System.Security.Cryptography;
+using TEAMModelOS.SDK.Extension;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public class DingDing
+    {
+        private const string url = "https://oapi.dingtalk.com/robot/send?access_token=";
+        private readonly HttpClient _httpClient;
+
+        public DingDing(HttpClient httpClient)
+        {
+            _httpClient = httpClient;
+        }
+
+        // <summary>
+        /// 發送需要加簽驗證的Bot訊息(msgtype為text)
+        /// </summary>
+        /// <param name="robotUrl">釘釘Robot發送Url</param>
+        /// <param name="secret">加簽密鑰</param>
+        /// <param name="msg">發送訊息</param>
+        /// <returns></returns>
+        public async Task SendBotMsg(string msg, GroupNames groupkey)
+        {
+            JObject jObject = new JObject()
+            {
+                new JProperty("msgtype","text"),
+                new JProperty("text",new JObject(
+                    new JProperty("content",msg)))
+            };
+            var content = new StringContent(jObject.ToString(), Encoding.UTF8, "application/json");
+            var keys = groupkey.GetDescriptionText().Split(',');
+            if (keys.Length == 1) await _httpClient.PostAsync($"{url}{keys[0]}", content);
+            else
+            {
+                var timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+                await _httpClient.PostAsync($"{url}{keys[0]}&timestamp={timestamp}&sign={BotAddSign(keys[1], timestamp)}", content);
+            }
+        }
+
+        // <summary>
+        /// 發送需要加簽驗證的Bot訊息(msgtype為text)
+        /// </summary>
+        /// <param name="robotUrl">釘釘Robot發送Url</param>
+        /// <param name="secret">加簽密鑰</param>
+        /// <param name="msg">發送訊息</param>
+        /// <returns></returns>
+        public async Task SendBotMsg(string msg, string accesstoken, string secret = null)
+        {
+            JObject jObject = new JObject()
+            {
+                new JProperty("msgtype","text"),
+                new JProperty("text",new JObject(
+                    new JProperty("content",msg)))
+            };
+
+            var content = new StringContent(jObject.ToString(), Encoding.UTF8, "application/json");
+            if (string.IsNullOrWhiteSpace(secret))
+                await _httpClient.PostAsync($"{url}{accesstoken}", content);
+            else
+            {
+                var timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+                await _httpClient.PostAsync($"{url}{accesstoken}&timestamp={timestamp}&sign={BotAddSign(secret, timestamp)}", content);
+            }
+
+
+        }
+
+        #region private
+        /// <summary>
+        /// 釘釘Bot簽名生成方法
+        /// </summary>
+        /// <param name="zTime"></param>
+        /// <returns></returns>
+        private static string BotAddSign(string secret, long zTime)
+        {
+            //"SEC6a6822db6567f79854a474002407cd9ac36da4d194b5fb79e073c35ef61119ed";
+            string stringToSign = zTime + "\n" + secret;
+            var encoding = new System.Text.ASCIIEncoding();
+            byte[] keyByte = encoding.GetBytes(secret);
+            byte[] messageBytes = encoding.GetBytes(stringToSign);
+            using (var hmacsha256 = new HMACSHA256(keyByte))
+            {
+                byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
+                return System.Web.HttpUtility.UrlEncode(Convert.ToBase64String(hashmessage), Encoding.UTF8);
+            }
+        }
+        #endregion
+    }
+
+    public enum GroupNames
+    {
+        [Description("ce63217d9c734a92fd91c7c9ceaa9b25e109cce94615a7f75288dc43865a6e20,SEC6a6822db6567f79854a474002407cd9ac36da4d194b5fb79e073c35ef61119ed")]
+        研發C組,
+        [Description("2c5ced0725b592b1a96f1fb800d6d9a15727986ef75923a838a4d24e6b8c9147,SEC66ff954306c1fd98b5b160e23c253649f22205e69a16fb26e18d136f49875a9e")]
+        客戶回饋群組,
+        [Description("f8bf19c9363e3b288e018856014bcbf89708f19b3aae009e203edd68af25c9fe")]
+        BB訂單群組,
+        [Description("a27b099b15a054374da41b9f66f72e5fc6b378e98418859f7c0ef46408941808")]
+        測試群組,
+        [Description("1a316ce4edc2db88231d40d80072b00f2751d7d9e2e5871c5dc061885b01c48d,SECff60201ac9b219943b9f8fc397fda1a617d0cbc140850f5ea9cb4f131479d39a")]
+        醍摩豆服務運維群組
+    }
+
+
+}

+ 154 - 0
TEAMModelOS.SDK/DI/SnowflakeID/SnowflakeID.cs

@@ -0,0 +1,154 @@
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public class SnowflakeId
+    {
+        private readonly IOptionsMonitor<SnowflakeIDOptions> _optionsMonitor;
+
+        // 開始時間截((new DateTime(2020, 1, 1, 0, 0, 0, DateTimeKind.Utc)-Jan1st1970).TotalMilliseconds)
+        private const long twepoch = 1577836800000L;
+        // 機器ID所佔的位數
+        private const int workerIdBits = 5;
+        // 數據標識ID所佔的位數
+        private const int datacenterIdBits = 5;
+        // 支持的最大機器ID,結果是31 (這個移位算法可以很快的計算出幾位二進制數所能表示的最大十進制數)
+        private const long maxWorkerId = -1L ^ (-1L << workerIdBits);
+        // 支持的最大數據標識ID,結果是31
+        private const long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
+        // 序列在ID中佔的位數 
+        private const int sequenceBits = 12;
+        // 數據標識ID向左移17位(12+5)
+        private const int datacenterIdShift = sequenceBits + workerIdBits;
+        // 機器ID向左移12位 
+        private const int workerIdShift = sequenceBits;
+        // 時間截向左移22位(5+5+12)
+        private const int timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
+        // 生成序列的掩碼,這里為4095 (0b111111111111=0xfff=4095)
+        private const long sequenceMask = -1L ^ (-1L << sequenceBits);
+        // 毫秒內序列(0~4095) 
+        private long sequence = 0L;
+        // 上次生成ID的時間截 
+        private long lastTimestamp = -1L;
+
+
+        // 數據中心ID(0~31,China請填8,Global請填1)
+        public long DatacenterId { get; private set; }
+        // 工作機器ID(0~31,依照數據中心,各地區自定)
+        public long WorkerId { get; private set; }
+
+
+
+        /// <summary>
+        /// 分散式ID產生器 (Snowflake算法,支援線程安全)
+        /// </summary>
+        /// <param name="datacenterId">數據中心ID (0~31)</param>
+        /// <param name="workerId">工作機器ID (0~31)</param>
+        public SnowflakeId(IOptionsMonitor<SnowflakeIDOptions> optionsMonitor)
+        {
+            if (optionsMonitor == null) throw new ArgumentNullException(nameof(optionsMonitor));
+            _optionsMonitor = optionsMonitor;
+            this.DatacenterId = optionsMonitor.CurrentValue.DatacenterId;
+            this.WorkerId = optionsMonitor.CurrentValue.WorkerId;
+        }
+
+        /// <summary>
+        /// 獲得下一個ID
+        /// </summary>
+        /// <returns></returns>
+        public long NextId()
+        {
+            lock (this)
+            {
+                long timestamp = GetCurrentTimestamp();
+                if (timestamp > lastTimestamp) //時間戳改變,毫秒內序列重置
+                {
+                    sequence = 0L;
+                }
+                else if (timestamp == lastTimestamp) //如果是同一時間生成的,則進行毫秒內序列
+                {
+                    sequence = (sequence + 1) & sequenceMask;
+                    if (sequence == 0) //毫秒內序列溢出
+                    {
+                        timestamp = GetNextTimestamp(lastTimestamp); //阻塞到下一個毫秒,獲得新的時間戳
+                    }
+                }
+                else   //當前時間小於上一次ID生成的時間戳,證明系統時鐘被回撥,此時需要做回撥處理
+                {
+                    sequence = (sequence + 1) & sequenceMask;
+                    if (sequence > 0)
+                    {
+                        timestamp = lastTimestamp;     //停留在最後一次時間戳上,等待系統時間追上後即完全度過了時鐘回撥問題
+                    }
+                    else   //毫秒內序列溢出
+                    {
+                        timestamp = lastTimestamp + 1;   //直接進位到下一個毫秒                          
+                    }
+                    //throw new Exception(string.Format("Clock moved backwards.  Refusing to generate id for {0} milliseconds", lastTimestamp - timestamp));
+                }
+
+                lastTimestamp = timestamp;       //上次生成ID的時間截
+
+                //移位並通過或運算拼到一起組成64位的ID
+                var id = ((timestamp - twepoch) << timestampLeftShift)
+                        | (DatacenterId << datacenterIdShift)
+                        | (WorkerId << workerIdShift)
+                        | sequence;
+                return id;
+            }
+        }
+
+        /// <summary>
+        /// 解析分散式ID
+        /// </summary>
+        /// <returns></returns>
+        public string ParseId(long Id)
+        {
+            StringBuilder sb = new StringBuilder();
+
+            var timestamp = (Id >> timestampLeftShift);
+            var time = Jan1st1970.AddMilliseconds(timestamp + twepoch);
+            sb.Append(time.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss:fff"));
+
+            var datacenterId = (Id ^ (timestamp << timestampLeftShift)) >> datacenterIdShift;
+            sb.Append("_" + datacenterId);
+
+            var workerId = (Id ^ ((timestamp << timestampLeftShift) | (datacenterId << datacenterIdShift))) >> workerIdShift;
+            sb.Append("_" + workerId);
+
+            var sequence = Id & sequenceMask;
+            sb.Append("_" + sequence);
+
+            return sb.ToString();
+        }
+
+        /// <summary>
+        /// 阻塞到下一個毫秒,直到獲得新的時間戳
+        /// </summary>
+        /// <param name="lastTimestamp">上次生成ID的時間截</param>
+        /// <returns>當前時間戳</returns>
+        private static long GetNextTimestamp(long lastTimestamp)
+        {
+            long timestamp = GetCurrentTimestamp();
+            while (timestamp <= lastTimestamp)
+            {
+                timestamp = GetCurrentTimestamp();
+            }
+            return timestamp;
+        }
+
+        /// <summary>
+        /// 獲取當前時間戳
+        /// </summary>
+        /// <returns></returns>
+        private static long GetCurrentTimestamp()
+        {
+            return (long)(DateTime.UtcNow - Jan1st1970).TotalMilliseconds;
+        }
+
+        private static readonly DateTime Jan1st1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+    }
+}

+ 28 - 0
TEAMModelOS.SDK/DI/SnowflakeID/SnowflakeIDExtensions.cs

@@ -0,0 +1,28 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public static class SnowflakeIDExtensions
+    {
+        /// <summary>
+        /// 分散式ID產生器 (Snowflake算法,支援線程安全)
+        /// </summary>
+        /// <param name="datacenterId">數據中心ID (0~31)</param>
+        /// <param name="workerId">工作機器ID (0~31)</param>
+        public static IServiceCollection AddSnowflakeId(this IServiceCollection services, long datacenterId, long workerId)
+        {
+            if (services == null) throw new ArgumentNullException(nameof(services));            
+            if (datacenterId > 31 || datacenterId < 0) throw new Exception("datacenterId only 0-31");            
+            if (workerId > 31 || workerId < 0) throw new Exception("workerId only 0-31");
+            
+            services.TryAddSingleton<SnowflakeId>();
+            services.Configure<SnowflakeIDOptions>(o => { o.DatacenterId = datacenterId; o.WorkerId = workerId; });
+
+            return services;
+        }
+    }
+}

+ 20 - 0
TEAMModelOS.SDK/DI/SnowflakeID/SnowflakeIDOptions.cs

@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.DI
+{
+    public class SnowflakeIDOptions
+    {
+        /// <summary>
+        /// 數據中心ID (0~31)
+        /// </summary>
+        public long DatacenterId { get; set; }
+        /// <summary>
+        /// 工作機器ID (0~31)
+        /// </summary>
+        public long WorkerId { get; set; }
+    }
+
+   
+}

+ 4 - 4
TEAMModelOS.SDK/Extension/DataResult/JsonRpcRequest/AzureTokenJsonRPCRequest.cs

@@ -1,18 +1,18 @@
-using TEAMModelOS.SDK.Extension.DataResult.RequestData;
+using TEAMModelOS.SDK;
 using System;
 using System.Collections.Generic;
 using System.Text;
 
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcRequest
+namespace TEAMModelOS.SDK
 {
     /// <summary>
     /// 
     /// </summary>
     /// <typeparam name="T"></typeparam>
-    public class AzureTokenJsonRPCRequest<T> : BaseJosnRPCRequest
+    public class AzureJsonRequest<T> : BaseJosnRequest
     {
 
-        public AzureTokenJsonRPCRequest (){
+        public AzureJsonRequest (){
             @params = new AzureTokenRequest<T>();
         }
         public AzureTokenRequest<T> @params { get; set; }

+ 2 - 2
TEAMModelOS.SDK/Extension/DataResult/JsonRpcRequest/BaseJosnRPCRequest.cs

@@ -1,10 +1,10 @@
 
 using System;
 
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcRequest
+namespace TEAMModelOS.SDK
 {
     
-    public abstract class BaseJosnRPCRequest
+    public abstract class BaseJosnRequest
     {
       //  public long requestTime { get; set; } = DateTime.Now.ToUniversalTime().Ticks - 621355968000000000;
        // public string jsonrpc { get; set; } = "2.0";

+ 3 - 2
TEAMModelOS.SDK/Extension/DataResult/JsonRpcRequest/JosnRPCRequest.cs

@@ -3,11 +3,12 @@ using System;
 using System.Collections.Generic;
 using System.Text;
 
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcRequest
+namespace TEAMModelOS.SDK
 {
     
-    public class JosnRPCRequest<T>:BaseJosnRPCRequest
+    public class JosnRequest<T>:BaseJosnRequest
     {
+
         public T @params { get; set; }
     }
 }

+ 15 - 0
TEAMModelOS.SDK/Extension/DataResult/JsonRequest/PaginationRequest.cs

@@ -0,0 +1,15 @@
+
+
+using TEAMModelOS.SDK;
+
+namespace TEAMModelOS.SDK
+{
+    public  class PaginationJsonRequest<T> : BaseJosnRequest
+    {
+        public PaginationJsonRequest()
+        {
+            @params = new PaginationRequest<T>();
+        }
+        public PaginationRequest<T> @params { get; set; }
+    }
+}

+ 2 - 2
TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/BaseJosnRPCResponse.cs

@@ -1,10 +1,10 @@
 
 using Microsoft.VisualBasic;
 
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
+namespace TEAMModelOS.SDK
 {
     
-    public class BaseJosnRPCResponse 
+    public class BaseResponse 
     {
       //  public string jsonrpc { get; set; } = "2.0";
        // public double id { get; set; } = 1;

+ 3 - 3
TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/DataJosnRPCResponse.cs

@@ -3,12 +3,12 @@ using System;
 using System.Collections.Generic;
 using System.Text;
 
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
+namespace TEAMModelOS.SDK
 {
     
-    public class DataJosnRPCResponse<T> : BaseJosnRPCResponse
+    public class DataJsonResponse<T> : BaseResponse
     {
-		public DataJosnRPCResponse() { 
+		public DataJsonResponse() { 
 		  result=  new JsonRPCResult<T>();
 		}
         public Dictionary<string, object> error { get; set; } = null;

+ 2 - 2
TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/EmptyJosnRPCResponse.cs

@@ -2,9 +2,9 @@
 using System.Collections.Generic;
 using System.Text;
 
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
+namespace TEAMModelOS.SDK
 {
-    public class EmptyJosnRPCResponse :BaseJosnRPCResponse
+    public class EmptyJosnResponse :BaseResponse
     {
         public object result { get; set; } = null;
         public Dictionary<string,object> error { get; set; } = null;

+ 3 - 3
TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/ErrorJosnRPCResponse.cs

@@ -2,12 +2,12 @@
 using System.Collections.Generic;
 using System.Text;
 
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
+namespace TEAMModelOS.SDK
 {
 
-    public class ErrorJosnRPCResponse : BaseJosnRPCResponse
+    public class ErrorJosnResponse : BaseResponse
     {
-        public ErrorJosnRPCResponse()
+        public ErrorJosnResponse()
         {
             error = new Dictionary<string, object>();
         }

+ 1 - 1
TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/ErrorModel.cs

@@ -2,7 +2,7 @@
 
 using System.Collections.Generic;
 
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
+namespace TEAMModelOS.SDK
 {
     
    

+ 1 - 1
TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/JsonRPCResult.cs

@@ -3,7 +3,7 @@ using System;
 using System.Collections.Generic;
 using System.Text;
 
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
+namespace TEAMModelOS.SDK
 {
     
     public class JsonRPCResult<T>

+ 5 - 5
TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/PageJosnRPCResponse.cs

@@ -3,16 +3,16 @@ using System;
 using System.Collections.Generic;
 using System.Text;
 
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
+namespace TEAMModelOS.SDK
 {
     
-    public class PageJosnRPCResponse<T> : BaseJosnRPCResponse
+    public class PageJosnResponse<T> : BaseResponse
     {
-		public PageJosnRPCResponse()
+		public PageJosnResponse()
 		{
-			result = new PageJsonRPCResult<T>();
+			result = new PageJsonResult<T>();
 		}
-		public   PageJsonRPCResult<T> result { get; set; }
+		public   PageJsonResult<T> result { get; set; }
 		public Dictionary<string, object> error { get; set; } = null;
 		public int code { get; set; } = 0;
 		public string message { get; set; } = "Success";

+ 15 - 0
TEAMModelOS.SDK/Extension/DataResult/JsonResponse/PageJsonResult.cs

@@ -0,0 +1,15 @@
+using TEAMModelOS.SDK;
+
+
+namespace TEAMModelOS.SDK
+{
+    
+    public class PageJsonResult<T> : JsonRPCResult<T>
+    {
+        public Pagination page { get; set; }
+
+        public PageJsonResult()
+        {
+        }
+    }
+}

+ 28 - 28
TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/JsonRPCResponseBuilder.cs

@@ -1,13 +1,13 @@
-using TEAMModelOS.SDK.Extension.DataResult.PageToken;
+using TEAMModelOS.SDK;
 
 using System;
 using System.Collections.Generic;
 using System.Text;
 
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
+namespace TEAMModelOS.SDK
 {
     
-    public  class JsonRPCResponseBuilder
+    public  class ResponseBuilder
     {
         private string message="Success";
         private object data;
@@ -20,66 +20,66 @@ namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
         private AzureTableToken token;
         private ErrorModel error =null;
         
-        public JsonRPCResponseBuilder()
+        public ResponseBuilder()
         {
         }
-        public JsonRPCResponseBuilder Success()
+        public ResponseBuilder Success()
         {
             error = null;
             return this;
         }
 
-        public JsonRPCResponseBuilder Success(String message)
+        public ResponseBuilder Success(String message)
         {
             this.message = message;
             return this;
         }
-        public static JsonRPCResponseBuilder custom()
+        public static ResponseBuilder custom()
         {
-            return new JsonRPCResponseBuilder();
+            return new ResponseBuilder();
         }
 
-        public JsonRPCResponseBuilder Data(object data)
+        public ResponseBuilder Data(object data)
         {
             this.data = data;
             return this;
         }
-		public JsonRPCResponseBuilder Error( int code, string message)
+		public ResponseBuilder Error( int code, string message)
 		{
 			
 			this.error = new ErrorModel { code=code, message=message, data = null };
 			return this;
 		}
-        public JsonRPCResponseBuilder Error(int code, Dictionary<string,object> errorData)
+        public ResponseBuilder Error(int code, Dictionary<string,object> errorData)
         {
            
             this.error = new ErrorModel { code = code, message = message ,data= errorData };
             return this;
         }
-        public JsonRPCResponseBuilder Error( int code)
+        public ResponseBuilder Error( int code)
 		{
 
             this.error = new ErrorModel { code = code, message = "Error", data = null };
             return this;
 		}
-        public JsonRPCResponseBuilder Error(int code, string message, Dictionary<string, object> errorData)
+        public ResponseBuilder Error(int code, string message, Dictionary<string, object> errorData)
         {
 
             this.error = new ErrorModel { code = code, message = message, data = errorData };
             return this;
         }
 
-        public JsonRPCResponseBuilder Extend(Dictionary<String, object> extend)
+        public ResponseBuilder Extend(Dictionary<String, object> extend)
         {
             this.extend = extend;
             return this;
         }
-        public JsonRPCResponseBuilder Token(AzureTableToken token)
+        public ResponseBuilder Token(AzureTableToken token)
         {
             this.token = token;
             return this;
         }
-        public JsonRPCResponseBuilder Page(Pagination page)
+        public ResponseBuilder Page(Pagination page)
         {
             this.pageSize = page.pageSize;
             this.currPage = page.currPage;
@@ -88,35 +88,35 @@ namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
             this.totalPage = (int)Math.Ceiling((double)this.total / (double)this.pageSize);
             return this;
         }
-        public JsonRPCResponseBuilder totalCount(int totalCount)
+        public ResponseBuilder totalCount(int totalCount)
         {
             this.total = totalCount;
             return this;
         }
 
-        public JsonRPCResponseBuilder CurrPage(int currPage)
+        public ResponseBuilder CurrPage(int currPage)
         {
             this.currPage = currPage;
             return this;
         }
 
-        public JsonRPCResponseBuilder PageSize(int pageSize)
+        public ResponseBuilder PageSize(int pageSize)
         {
             this.pageSize = pageSize;
             return this;
         }
 
-        public JsonRPCResponseBuilder TotalPage(int totalPage)
+        public ResponseBuilder TotalPage(int totalPage)
         {
             this.totalPage = totalPage;
             return this;
         }
-        public BaseJosnRPCResponse build()
+        public BaseResponse build()
         {
 
             object baseResponse = null;
             if (error != null) {
-                ErrorJosnRPCResponse errorJosnRPCResponse = new ErrorJosnRPCResponse();
+                ErrorJosnResponse errorJosnRPCResponse = new ErrorJosnResponse();
                 errorJosnRPCResponse.error = error.data;
                 error.code = error.code;
                 error.message = error.message;
@@ -128,7 +128,7 @@ namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
             }
             if (null != this.data && this.token != null)
             {
-                TokenJosnRPCResponse<object> response = new TokenJosnRPCResponse<object>();
+                TokenJosnResponse<object> response = new TokenJosnResponse<object>();
                 response.result.data = this.data;
                 response.result.extend = this.extend;
                 response.result.azureToken = this.token;
@@ -139,7 +139,7 @@ namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
             }
             else if (null != this.data && this.total > 0 && this.currPage > 0 && this.pageSize > 0 && this.totalPage > 0)
             {
-                PageJosnRPCResponse<object> response = new PageJosnRPCResponse<object>();
+                PageJosnResponse<object> response = new PageJosnResponse<object>();
                 response.result.data = this.data;
                 response.result.page = new Pagination(this.total, this.currPage, this.pageSize, this.totalPage);
                 response.result.extend = this.extend;
@@ -149,7 +149,7 @@ namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
             }
             else if (this.data != null)
             {
-                DataJosnRPCResponse<object> response = new DataJosnRPCResponse<object>();
+                DataJsonResponse<object> response = new DataJsonResponse<object>();
                 response.result.data = this.data;
                 response.result.extend = this.extend;
                 response.message = message;
@@ -157,7 +157,7 @@ namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
                 baseResponse = response;
             }
             else if (this.data == null) {
-                DataJosnRPCResponse<object> response = new DataJosnRPCResponse<object>();
+                DataJsonResponse<object> response = new DataJsonResponse<object>();
                 response.result.data = this.data;
                 response.result.extend = this.extend;
                 response.message = message;
@@ -166,9 +166,9 @@ namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
             }
             else
             {
-                return new EmptyJosnRPCResponse() ;
+                return new EmptyJosnResponse() ;
             }
-            return (BaseJosnRPCResponse)baseResponse;
+            return (BaseResponse)baseResponse;
         }
          
     }

+ 20 - 0
TEAMModelOS.SDK/Extension/DataResult/JsonResponse/TokenJosnResponse.cs

@@ -0,0 +1,20 @@
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK
+{
+    
+    public class TokenJosnResponse<T>: BaseResponse
+    {
+		public TokenJosnResponse()
+		{
+			result = new TokenJsonResult<T>();
+		}
+		public  TokenJsonResult<T> result { get; set; }
+		public Dictionary<string, object> error { get; set; } = null;
+		public int code { get; set; } = 0;
+		public string message { get; set; } = "Success";
+	}
+}

+ 4 - 4
TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/TokenJsonRPCResult.cs

@@ -1,17 +1,17 @@
-using TEAMModelOS.SDK.Extension.DataResult.PageToken;
+using TEAMModelOS.SDK;
 
 using System;
 using System.Collections.Generic;
 using System.Text;
 
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
+namespace TEAMModelOS.SDK
 {
     
-    public class TokenJsonRPCResult<T> : JsonRPCResult<T>
+    public class TokenJsonResult<T> : JsonRPCResult<T>
     {
        
         public AzureTableToken azureToken { get; set; }
-        public TokenJsonRPCResult() { }
+        public TokenJsonResult() { }
        // public int code { get; set; } = 0;
       //  public string message { get; set; } = "Success";
     }

+ 0 - 15
TEAMModelOS.SDK/Extension/DataResult/JsonRpcRequest/PaginationJosnRPCRequest.cs

@@ -1,15 +0,0 @@
-
-
-using TEAMModelOS.SDK.Extension.DataResult.RequestData;
-
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcRequest
-{
-    public  class PaginationJosnRPCRequest<T> : BaseJosnRPCRequest
-    {
-        public PaginationJosnRPCRequest()
-        {
-            @params = new PaginationRequest<T>();
-        }
-        public PaginationRequest<T> @params { get; set; }
-    }
-}

+ 0 - 17
TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/JosnRPCResponse.cs

@@ -1,17 +0,0 @@
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
-{
-    
-    public class JosnRPCResponse<T>:BaseJosnRPCResponse
-    {
-        public  T result { get; set; }
-
-        public Dictionary<string, object> error { get; set; } = null;
-        public int code { get; set; } = 0;
-        public string message { get; set; } = "Success";
-    }
-}

+ 0 - 15
TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/PageJsonRPCResult.cs

@@ -1,15 +0,0 @@
-using TEAMModelOS.SDK.Extension.DataResult.PageToken;
-
-
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
-{
-    
-    public class PageJsonRPCResult<T> : JsonRPCResult<T>
-    {
-        public Pagination page { get; set; }
-
-        public PageJsonRPCResult()
-        {
-        }
-    }
-}

+ 0 - 20
TEAMModelOS.SDK/Extension/DataResult/JsonRpcResponse/TokenJosnRPCResponse.cs

@@ -1,20 +0,0 @@
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse
-{
-    
-    public class TokenJosnRPCResponse<T>: BaseJosnRPCResponse
-    {
-		public TokenJosnRPCResponse()
-		{
-			result = new TokenJsonRPCResult<T>();
-		}
-		public  TokenJsonRPCResult<T> result { get; set; }
-		public Dictionary<string, object> error { get; set; } = null;
-		public int code { get; set; } = 0;
-		public string message { get; set; } = "Success";
-	}
-}

+ 1 - 1
TEAMModelOS.SDK/Extension/DataResult/PageToken/AzurePagination.cs

@@ -1,7 +1,7 @@
 
 using System.Collections.Generic;
 
-namespace TEAMModelOS.SDK.Extension.DataResult.PageToken
+namespace TEAMModelOS.SDK
 {
     
     public class AzurePagination<T>

+ 1 - 1
TEAMModelOS.SDK/Extension/DataResult/PageToken/AzureTableToken.cs

@@ -1,7 +1,7 @@
 
 using System.ComponentModel.DataAnnotations;
 
-namespace TEAMModelOS.SDK.Extension.DataResult.PageToken
+namespace TEAMModelOS.SDK
 {
     
     public class AzureTableToken

+ 1 - 1
TEAMModelOS.SDK/Extension/DataResult/PageToken/Pagination.cs

@@ -2,7 +2,7 @@
 using System;
 using System.Collections.Generic;
 
-namespace TEAMModelOS.SDK.Extension.DataResult.PageToken
+namespace TEAMModelOS.SDK
 {
     
     public class Pagination

+ 0 - 12
TEAMModelOS.SDK/Extension/DataResult/PageToken/PaginationData.cs

@@ -1,12 +0,0 @@
-using System.Collections.Generic;
-
-namespace TEAMModelOS.SDK.Extension.DataResult.PageToken
-{
-    public class PaginationData<T>:Pagination
-    {
-        public PaginationData(int currPage, int pageSize, int total) : base(currPage, pageSize, total)
-        {
-        }
-        public List<T> data { get; set; }
-    }
-}

+ 2 - 2
TEAMModelOS.SDK/Extension/DataResult/RequestData/AzureTokenRequest.cs

@@ -1,9 +1,9 @@
-using TEAMModelOS.SDK.Extension.DataResult.PageToken;
+using TEAMModelOS.SDK;
 using System;
 using System.Collections.Generic;
 using System.Text;
 
-namespace TEAMModelOS.SDK.Extension.DataResult.RequestData
+namespace TEAMModelOS.SDK
 {
    public class AzureTokenRequest<T> :BaseRequest
    {

+ 1 - 1
TEAMModelOS.SDK/Extension/DataResult/RequestData/BaseRequest.cs

@@ -1,7 +1,7 @@
 using System;
 using System.Collections.Generic;
 
-namespace TEAMModelOS.SDK.Extension.DataResult.RequestData
+namespace TEAMModelOS.SDK
 {
     public class BaseRequest
     {

+ 2 - 2
TEAMModelOS.SDK/Extension/DataResult/RequestData/PaginationRequest.cs

@@ -1,6 +1,6 @@
-using TEAMModelOS.SDK.Extension.DataResult.PageToken;
+using TEAMModelOS.SDK;
 
-namespace TEAMModelOS.SDK.Extension.DataResult.RequestData
+namespace TEAMModelOS.SDK
 {
     public class PaginationRequest<T> : BaseRequest
     {

+ 0 - 16
TEAMModelOS.SDK/Extension/DataResult/ResponseData/BaseResponse.cs

@@ -1,16 +0,0 @@
-
-using System.Collections.Generic;
-
-namespace TEAMModelOS.SDK.Extension.DataResult.ResponseData
-{
-    
-    public class BaseResponse : TimeStampResponse
-    {
-        public Dictionary<string, object> extend { get; set; }
-        public string message { get; set; } = "success";
-        public int code { get; set; }
-        public BaseResponse()
-        {
-        }
-    }
-}

+ 0 - 14
TEAMModelOS.SDK/Extension/DataResult/ResponseData/DataResponse.cs

@@ -1,14 +0,0 @@
-
-
-namespace TEAMModelOS.SDK.Extension.DataResult.ResponseData
-{
-    
-    public class DataResponse<T> : BaseResponse
-    {
-        public T data { get; set; }
-
-        public DataResponse()
-        {
-        }
-    }
-}

+ 0 - 15
TEAMModelOS.SDK/Extension/DataResult/ResponseData/PageDatasResponse.cs

@@ -1,15 +0,0 @@
-using TEAMModelOS.SDK.Extension.DataResult.PageToken;
-
-
-namespace TEAMModelOS.SDK.Extension.DataResult.ResponseData
-{
-    
-    public class PageDatasResponse<T> : DataResponse<T>
-    {
-        public Pagination page { get; set; }
-
-        public PageDatasResponse()
-        {
-        }
-    }
-}

+ 0 - 162
TEAMModelOS.SDK/Extension/DataResult/ResponseData/ResponseBuilder.cs

@@ -1,162 +0,0 @@
-using TEAMModelOS.SDK.Extension.DataResult.PageToken;
-
-using System;
-using System.Collections.Generic;
-
-
-namespace TEAMModelOS.SDK.Extension.DataResult.ResponseData
-{
-    
-    public class ResponseBuilder
-    {
-        private string message = "success";
-        private object data;
-        private int code = 0;
-       // private IList<object> datas;
-        private long total;
-        private int currPage;
-        private int pageSize;
-        private int totalPage;
-        private Dictionary<string, object> extend;
-        private Pagination page;
-        private AzureTableToken  token;
-        public ResponseBuilder()
-        {
-        }
-
-        public static ResponseBuilder custom()
-        {
-            return new ResponseBuilder();
-        }
-
-        public BaseResponse build()
-        {
-            if (this.total > 0 && this.pageSize > 0 )
-            {
-                this.totalPage = (int)Math.Ceiling((double)this.total / (double)this.pageSize);
-            }
-            object baseResponse;
-           
-             if (null != this.data && this.token!=null)
-            {
-                TokenPageDatasResponse<object> pageDatasResponse = new TokenPageDatasResponse<object>();
-                pageDatasResponse.code= this.code;
-                pageDatasResponse.data= this.data;
-                pageDatasResponse.message= this.message;
-                pageDatasResponse.extend=this.extend;
-                pageDatasResponse.azureToken = this.token;
-                baseResponse = pageDatasResponse;
-            }
-            else if (null != this.data && this.total > 0 && this.currPage > 0 && this.pageSize > 0 && this.totalPage > 0)
-            {
-                PageDatasResponse<object> pageDatasResponse = new PageDatasResponse<object>();
-                pageDatasResponse.code = this.code;
-                pageDatasResponse.data = this.data;
-                pageDatasResponse.message = this.message;
-                pageDatasResponse.page = new Pagination(this.total, this.currPage, this.pageSize, this.totalPage);
-                pageDatasResponse.extend = this.extend;
-                baseResponse = pageDatasResponse;
-            }
-            else if (this.data != null)
-            {
-                DataResponse<object> datasResponse = new DataResponse<object>();
-                datasResponse.code=this.code;
-                datasResponse.data=this.data;
-                datasResponse.message=this.message;
-                datasResponse.extend=this.extend;
-                baseResponse = datasResponse;
-            }
-            else
-            {
-                baseResponse = new BaseResponse();
-                ((BaseResponse)baseResponse).message=this.message;
-                ((BaseResponse)baseResponse).code=this.code;
-                ((BaseResponse)baseResponse).extend=this.extend;
-            }
-            return (BaseResponse)baseResponse;
-        }
-
-        
-
-        public ResponseBuilder Extend(Dictionary<String, object> extend)
-        {
-            this.extend = extend;
-            return this;
-        }
-        public ResponseBuilder Token(AzureTableToken token)
-        {
-            this.token = token;
-            return this;
-        }
-        public ResponseBuilder Data(object data)
-        {
-            this.data = data;
-            return this;
-        }
-       
-        public ResponseBuilder Page(Pagination page)
-        {
-            this.pageSize = page.pageSize;
-            this.currPage = page.currPage;
-            this.total = page.total;
-            this.page = page;
-            this.totalPage = (int)Math.Ceiling((double)this.total / (double)this.pageSize);
-            return this;
-        }
-        public ResponseBuilder totalCount(int totalCount)
-        {
-            this.total = totalCount;
-            return this;
-        }
-
-        public ResponseBuilder CurrPage(int currPage)
-        {
-            this.currPage = currPage;
-            return this;
-        }
-
-        public ResponseBuilder PageSize(int pageSize)
-        {
-            this.pageSize = pageSize;
-            return this;
-        }
-
-        public ResponseBuilder TotalPage(int totalPage)
-        {
-            this.totalPage = totalPage;
-            return this;
-        }
-
-        public ResponseBuilder success()
-        {
-            return this;
-        }
-
-        public ResponseBuilder success(String message)
-        {
-            this.message = message;
-            return this;
-        }
-
-        public ResponseBuilder success(String message, int code)
-        {
-            this.message = message;
-            this.code = code;
-            return this;
-        }
-
-        public ResponseBuilder failed(String message, int code)
-        {
-            this.code = code;
-            this.message = message;
-            return this;
-        }
-
-        public ResponseBuilder failed(String message)
-        {
-            this.code = 1;
-            this.message = message;
-            return this;
-        }
-    }
-}

+ 0 - 16
TEAMModelOS.SDK/Extension/DataResult/ResponseData/TimeStampResponse.cs

@@ -1,16 +0,0 @@
-
-using System;
-
-
-namespace TEAMModelOS.SDK.Extension.DataResult.ResponseData
-{
-    
-    public class TimeStampResponse
-    {
-        public long responseTime { get; set; } = DateTime.Now.ToUniversalTime().Ticks - 621355968000000000;
-        public TimeStampResponse()
-        {
-
-        }
-    }
-}

+ 0 - 14
TEAMModelOS.SDK/Extension/DataResult/ResponseData/TokenPageDatasResponse.cs

@@ -1,14 +0,0 @@
-using TEAMModelOS.SDK.Extension.DataResult.PageToken;
-
-
-
-namespace TEAMModelOS.SDK.Extension.DataResult.ResponseData
-{
-    
-    public class TokenPageDatasResponse<T> : DataResponse<T>
-    {
-        public AzureTableToken azureToken { get; set; }
-
-        public TokenPageDatasResponse() { }
-    }
-}

+ 22 - 0
TEAMModelOS.SDK/Extension/EnumExtensions.cs

@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Reflection;
+using System.Text;
+
+namespace TEAMModelOS.SDK.Extension
+{
+    public static class EnumExtensions
+    {
+        /// <summary>
+        /// 取得Enum描述值
+        /// </summary>       
+        public static string GetDescriptionText(this Enum source)
+        {
+            FieldInfo fi = source.GetType().GetField(source.ToString());
+            DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
+            if (attributes.Length > 0) return attributes[0].Description;
+            else return source.ToString();
+        }
+    }
+}

+ 94 - 0
TEAMModelOS.SDK/Extension/HttpContextExtensions.cs

@@ -0,0 +1,94 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Primitives;
+
+namespace TEAMModelOS.SDK.Extension
+{
+    public static class HttpContextExtensions
+    {
+        /// <summary>
+        /// 取得驗證金鑰,Authorization
+        /// </summary>        
+        public static string GetToken(this HttpContext httpContext)
+        {
+            return httpContext.Request.Headers["Authorization"].ToString();
+        }
+
+        /// <summary>
+        /// 取得JWT驗證金鑰,Authorization Bearer
+        /// </summary>
+        /// <param name="httpContext"></param>
+        /// <returns></returns>
+        public static string GetJwtToken(this HttpContext httpContext)
+        {
+            var token = string.Empty;
+            string authorization = httpContext.Request.Headers["Authorization"].ToString();
+            if (!string.IsNullOrWhiteSpace(authorization) && authorization.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
+            {
+                token = authorization.Substring("Bearer ".Length).Trim();
+            }
+            return token;
+        }
+
+        /// <summary>
+        /// 取得遠端呼叫的IP
+        /// </summary>        
+        public static string GetRemoteIP(this HttpContext httpContext)
+        {            
+                return httpContext?.Connection?.RemoteIpAddress?.ToString();            
+        }
+
+        /// <summary>
+        /// 取得X-Auth-Key值
+        /// </summary>        
+        /// <param name="key">Key Name</param>
+        /// <returns></returns>
+        public static string GetXAuth(this HttpContext httpContext, string key = null)
+        {
+            try
+            {
+                if (httpContext.Request.Headers.TryGetValue($"X-Auth-{key}", out StringValues value))
+                    return value.ToString();
+                else
+                    return null;
+            }
+            catch
+            {
+                return null;
+            }
+        }
+
+        /// <summary>
+        /// 取得User-Agent值
+        /// </summary>       
+        public static string GetUserAgent(this HttpContext httpContext)
+        {
+            try
+            {
+                return httpContext.Request.Headers["User-Agent"].ToString();
+            }
+            catch
+            {
+                return null;
+            }
+        }
+
+        /// <summary>
+        /// 取得Scheme值
+        /// </summary>      
+        public static string GetScheme(this HttpContext httpContext)
+        {           
+                return httpContext?.Request?.Scheme;           
+        }
+
+        /// <summary>
+        /// 取得HostName值
+        /// </summary>        
+        public static string GetHostName(this HttpContext httpContext)
+        {            
+                return httpContext?.Request?.Host.ToString();          
+        }
+    }
+}

+ 52 - 0
TEAMModelOS.SDK/Extension/JsonExtensions.cs

@@ -0,0 +1,52 @@
+using System;
+using System.Buffers;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Text.Json;
+
+namespace TEAMModelOS.SDK.Extension
+{
+    public static class JsonExtensions
+    {
+        public static string ToJsonString(this JsonDocument jdoc)
+        {
+            var bufferWriter = new ArrayBufferWriter<byte>();
+            using var writer = new Utf8JsonWriter(bufferWriter, new JsonWriterOptions { Indented = true });
+            jdoc.WriteTo(writer);
+            writer.Flush();
+            return Encoding.UTF8.GetString(bufferWriter.WrittenSpan);
+        }
+
+        public static string ToJsonString(this JsonElement jelement)
+        {
+            var bufferWriter = new ArrayBufferWriter<byte>();
+            using var writer = new Utf8JsonWriter(bufferWriter, new JsonWriterOptions { Indented = true });
+            jelement.WriteTo(writer);
+            writer.Flush();
+            return Encoding.UTF8.GetString(bufferWriter.WrittenSpan);
+        }
+
+        public static string ToJsonString(this Object obj, JsonSerializerOptions option = null)
+        {
+            var json = JsonSerializer.Serialize(obj, option);
+            return json;
+        }
+
+        public static T ToObject<T>(this JsonDocument jdoc, JsonSerializerOptions options = null)
+        {
+            return jdoc.RootElement.ToObject<T>(options);
+        }
+
+        public static T ToObject<T>(this JsonElement jelement, JsonSerializerOptions options = null)
+        {
+            var bufferWriter = new ArrayBufferWriter<byte>();
+            using var writer = new Utf8JsonWriter(bufferWriter);
+            jelement.WriteTo(writer);
+            writer.Flush();
+            return JsonSerializer.Deserialize<T>(bufferWriter.WrittenSpan, options);
+        }        
+
+        
+    }
+}

+ 13 - 10
TEAMModelOS.SDK/Extension/MessagePush/Implements/SendCloudService.cs

@@ -1,17 +1,19 @@
-
+
 using TEAMModelOS.SDK.Extension.MessagePush.Interfaces;
 using TEAMModelOS.SDK.Extension.MessagePush.Model;
 using System;
 using System.Collections.Generic;
 using System.Threading.Tasks;
 using TEAMModelOS.SDK.Extension.Language.Interfaces;
-using TEAMModelOS.SDK.Module.AzureTable.Interfaces;
+
 using Microsoft.Extensions.Options;
 using TEAMModelOS.SDK.Extension.Language.Model;
 using TEAMModelOS.SDK.Helper.Common.JsonHelper;
 using TEAMModelOS.SDK.Helper.Security.Md5Hash;
 using TEAMModelOS.SDK.Helper.Network.HttpHelper;
 using TEAMModelOS.SDK.Extension.HttpClient.Implements;
+using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
+using TEAMModelOS.SDK.DI;
 
 namespace TEAMModelOS.SDK.Extension.MessagePush.Implements
 {
@@ -19,9 +21,9 @@ namespace TEAMModelOS.SDK.Extension.MessagePush.Implements
     {
         public SmsSendCloud smsSendCloud;
         public ILanguageService _languageService;
-        public IAzureTableDBRepository _azureTableDBRepository;
+        public AzureStorageFactory _azureTableDBRepository;
         public HttpClientSendCloud _httpClientService;
-        public SendCloudService(IOptions<SmsSendCloud> _option, ILanguageService languageService , IAzureTableDBRepository azureTableDBRepository , HttpClientSendCloud httpClientService )
+        public SendCloudService(IOptions<SmsSendCloud> _option, ILanguageService languageService , AzureStorageFactory azureTableDBRepository , HttpClientSendCloud httpClientService )
         {
             _azureTableDBRepository = azureTableDBRepository;
             _languageService = languageService;
@@ -53,11 +55,11 @@ namespace TEAMModelOS.SDK.Extension.MessagePush.Implements
                     {
                         { "BizNum", BizNum },{ "BizCode", BizCode["code"] }, { "Language", Language["code"] } ,
                     };
-                    SmsConfig smsConfig = await _azureTableDBRepository.FindOneByDict<SmsConfig>(dict);
+                    List<SmsConfig> smsConfig = await _azureTableDBRepository.FindListByDict<SmsConfig>(dict);
 
-                    if (smsConfig != null && smsConfig.RowKey != null)
+                    if (smsConfig.IsNotEmpty()  && smsConfig[0].RowKey != null)
                     {
-                        smsConfigs.Add(smsConfig);
+                        smsConfigs.Add(smsConfig[0]);
                     }
                     else {
                         DateTimeOffset now = DateTimeOffset.Now;
@@ -104,12 +106,13 @@ namespace TEAMModelOS.SDK.Extension.MessagePush.Implements
             {
                 { "BizNum", BizNum },{ "BizCode", BizCode }, { "Language", SmsLang } ,
             };
-            SmsConfig smsConfig   =  await _azureTableDBRepository.FindOneByDict<SmsConfig>(dict);
+            List<SmsConfig> smsConfig = await _azureTableDBRepository.FindListByDict<SmsConfig>(dict);
 
-            if (smsConfig != null && smsConfig.RowKey != null )
+            if (smsConfig.IsNotEmpty() && smsConfig[0].RowKey != null)
             {
+             
                 //默认调用英文,不管是否包含,发送时会去处理相关信息
-                int.TryParse(smsConfig.Template ,out templateId);
+                int.TryParse(smsConfig[0].Template ,out templateId);
             }
             //else {
             //    throw new BizException("");

+ 94 - 0
TEAMModelOS.SDK/Extension/Utils.cs

@@ -0,0 +1,94 @@
+using Microsoft.AspNetCore.Cryptography.KeyDerivation;
+using System;
+using System.Collections.Generic;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace TEAMModelOS.SDK.Extension
+{
+    public class Utils
+    {
+        private static RNGCryptoServiceProvider _random = new RNGCryptoServiceProvider();
+
+        public static string HashedPassword(string password, string salt)
+        {
+            byte[] hashBytes = KeyDerivation.Pbkdf2(
+                password: password,
+                salt: Encoding.UTF8.GetBytes(salt), //SHA1鹽(8-20字節),SHA256(32字節)
+                prf: KeyDerivationPrf.HMACSHA1,
+                iterationCount: 10000, //hash次數,越多次代表破解難度變高,但效能會差點
+                numBytesRequested: 256 / 8 //指定得出結果長度
+            );
+
+            string hashText = BitConverter.ToString(hashBytes).Replace("-", string.Empty);
+            return hashText;
+        }
+
+        /// <summary>
+        /// 建立真隨機字串(CSPRNG),適用密碼、鹽
+        /// </summary>
+        /// <param name="stringLength">長度</param>
+        /// <param name="key">要限制的字元串(長度需大於等於8),如果為null或者小於8,預設為"abcdefghijklmnopqrstuvwxyz1234567890"</param>
+        /// <returns></returns>
+        public static string CreatSaltString(int stringLength, string key = null)
+        {
+            ReadOnlySpan<char> span;
+            if (key == null || key.Length < 8)
+                span = "abcdefghijklmnopqrstuvwxyz1234567890";
+            else
+                span = key.AsSpan();
+
+            int length = span.Length;
+            StringBuilder randomString = new StringBuilder(length);
+            for (int i = 0; i < stringLength; ++i)
+            {
+                randomString.Append(span[SetRandomSeeds(length)]);
+            }
+            return randomString.ToString();
+        }
+
+        /// <summary>
+        /// 建立真隨機整數數字(CSPRNG),適用亂數、隨機編號
+        /// </summary>
+        /// <param name="max">最大值</param>
+        public static int CreatSaltInt(int max)
+        {
+            var bytes = new byte[4];
+            _random.GetBytes(bytes);
+            int value = BitConverter.ToInt32(bytes, 0);
+            value = value % (max + 1);
+            if (value < 0) value = -value;
+            return value;
+        }
+
+        /// <summary>
+        /// 建立真隨機整數數字(CSPRNG),適用亂數、隨機編號
+        /// </summary>
+        /// <param name="min">最小值</param>
+        /// <param name="max">最大值</param>
+        public static int CreatSaltInt(int min, int max)
+        {
+            int value = CreatSaltInt(max - min) + min;
+            return value;
+        }        
+
+        public static Dictionary<string, string> ParseConnectionString(string connectionString)
+        {
+            var d = new Dictionary<string, string>();
+            foreach (var item in connectionString.Split(';',StringSplitOptions.RemoveEmptyEntries))
+            {
+                var a = item.IndexOf('=');
+                d.Add(item.Substring(0, a), item.Substring(a + 1));
+            }
+            return d;
+        }
+
+        private static int SetRandomSeeds(int length)
+        {
+            decimal maxValue = (decimal)long.MaxValue;
+            byte[] array = new byte[8];
+            _random.GetBytes(array);
+            return (int)(Math.Abs(BitConverter.ToInt64(array, 0)) / maxValue * length);
+        }
+    }
+}

+ 1 - 1
TEAMModelOS.SDK/Helper/Security/RSACrypt/RSAUtils.cs

@@ -1,4 +1,4 @@
-using System;
+using System;
 using System.IO;
 using System.Security.Cryptography;
 namespace TEAMModelOS.SDK.Helper.Security.RSACrypt

+ 0 - 12
TEAMModelOS.SDK/Module/AzureBlob/Configuration/AzureBlobConfig.cs

@@ -1,12 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace TEAMModelOS.SDK.Module.AzureBlob.Configuration
-{
-    public class AzureBlobConfig
-    {
-        public readonly static string AZURE_CHINA = "AzureChina";
-        public readonly static string AZURE_GLOBAL = "AzureGlobal";
-    }
-}

+ 0 - 19
TEAMModelOS.SDK/Module/AzureBlob/Configuration/AzureBlobOptions.cs

@@ -1,19 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace TEAMModelOS.SDK.Module.AzureBlob.Configuration
-{
-   public class AzureBlobOptions
-    {
-        public string ConnectionString { get; set; } 
-        public string AzureTableDialect { get; set; }
-        public string Container { get; set; }
-        /// <summary>
-        /// 
-        /// </summary>
-        public AzureBlobOptions()
-        {
-        }
-    }
-}

+ 0 - 24
TEAMModelOS.SDK/Module/AzureBlob/Configuration/AzureBlobServiceBuilder.cs

@@ -1,24 +0,0 @@
-using Microsoft.Extensions.DependencyInjection;
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace TEAMModelOS.SDK.Module.AzureBlob.Configuration
-{
-     public  class AzureBlobServiceBuilder : ServiceCollection
-    {
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <param name="services"></param>
-        public AzureBlobServiceBuilder(IServiceCollection services)
-        {
-            Services = services ?? throw new ArgumentNullException(nameof(services));
-        }
-
-        /// <summary>
-        /// 
-        /// </summary>
-        public IServiceCollection Services { get; }
-    }
-}

+ 0 - 48
TEAMModelOS.SDK/Module/AzureBlob/Configuration/AzureBlobServiceCollectionExtensions.cs

@@ -1,48 +0,0 @@
-using TEAMModelOS.SDK.Module.AzureBlob.Implements;
-using TEAMModelOS.SDK.Module.AzureBlob.Interfaces;
-using Microsoft.Extensions.DependencyInjection;
-
-namespace TEAMModelOS.SDK.Module.AzureBlob.Configuration
-{
-    public static class AzureBlobServiceCollectionExtensions
-    {
-        public static AzureBlobServiceBuilder Builder { get; set; }
-
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <param name="services"></param>
-        /// <returns></returns>
-        private static AzureBlobServiceBuilder AddServerBuilder(this IServiceCollection services)
-        {
-            return new AzureBlobServiceBuilder(services);
-        }
-
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <param name="services"></param>
-        /// <returns></returns>
-        public static AzureBlobServiceBuilder AddAzureBlobStorage(this IServiceCollection services)
-        {
-            if (Builder == null)
-            {
-                Builder = services.AddServerBuilder();
-            }
-            services.AddSingleton<IAzureBlobDBRepository, AzureBlobDBRepository>();
-            return Builder;
-        }
-
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <param name="builder"></param>
-        /// <param name="_connectionString"></param>
-        /// <returns></returns>
-        public static AzureBlobServiceBuilder AddConnection(this AzureBlobServiceBuilder builder, AzureBlobOptions databaseOptions)
-        {
-            builder.Services.AddSingleton(databaseOptions);
-            return builder;
-        }
-    }
-}

+ 0 - 43
TEAMModelOS.SDK/Module/AzureBlob/Configuration/BlobClientSingleton.cs

@@ -1,43 +0,0 @@
-
-using Microsoft.WindowsAzure.Storage;
-using Microsoft.WindowsAzure.Storage.Blob;
-using System;
-
-namespace TEAMModelOS.SDK.Module.AzureBlob.Configuration
-{
-    public sealed class BlobClientSingleton
-    {
-        private static string _connectionString;
-        private CloudBlobClient BlobClient;
-
-        private BlobClientSingleton() { }
-
-        public CloudBlobClient GetBlobClient()
-        {
-            if (BlobClient != null)
-            {
-                return BlobClient;
-            }
-            else
-            {
-                getInstance(_connectionString);
-                return BlobClient;
-            }
-        }
-
-        public static BlobClientSingleton getInstance(string connectionString)
-        {
-            _connectionString = connectionString;
-            return SingletonInstance.instance;
-        }
-
-        private static class SingletonInstance
-        {
-            public static BlobClientSingleton instance = new BlobClientSingleton()
-            {
-                BlobClient = CloudStorageAccount.Parse(_connectionString).CreateCloudBlobClient()
-               //BlobClient = new  CloudBlobClient(new Uri(_connectionString))
-            };
-        }
-    }
-}

+ 0 - 18
TEAMModelOS.SDK/Module/AzureBlob/Configuration/BlobFileDto.cs

@@ -1,18 +0,0 @@
-using Microsoft.WindowsAzure.Storage.Blob;
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace TEAMModelOS.SDK.Module.AzureBlob.Configuration
-{
-    public class BlobFileDto
-    {
-        public string name { get; set; }
-        public long length { get; set; }
-        public string contentType { get; set; }
-        public long created { get; set; }
-        public long lastModified { get; set; }
-        public string url { get; set; }
-        public string BlobType { get; set; }
-    }
-}

+ 0 - 12
TEAMModelOS.SDK/Module/AzureBlob/Container/FileContainer.cs

@@ -1,12 +0,0 @@
-namespace TEAMModelOS.SDK.Module.AzureBlob.Container
-{
-    public class FileContainer : IBlobContainer
-    {
-        public string Container { get; private set; } = "filecontainer";
-
-        public string GetContainer()
-        {
-            return Container;
-        }
-    }
-}

+ 0 - 11
TEAMModelOS.SDK/Module/AzureBlob/Container/IBlobContainer.cs

@@ -1,11 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace TEAMModelOS.SDK.Module.AzureBlob.Container
-{
-    public interface IBlobContainer
-    {
-        string GetContainer();
-    }
-}

+ 0 - 0
TEAMModelOS.SDK/Module/AzureBlob/Container/ImageContainer.cs


Vissa filer visades inte eftersom för många filer har ändrats