CrazyIter_Bin 11 月之前
父節點
當前提交
ebf19af162

+ 52 - 0
HTEXCosmosDB/Controllers/IndexController.cs

@@ -0,0 +1,52 @@
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Azure.Cosmos;
+using System.Text.Json;
+
+namespace HTEXCosmosDB.Controllers
+{
+    [ProducesResponseType(StatusCodes.Status200OK)]
+    [ProducesResponseType(StatusCodes.Status400BadRequest)]
+    [Route("index")]
+    [ApiController]
+    public class IndexController: ControllerBase
+    {
+        private readonly AzureCosmosFactory _azureCosmosFactory;
+        public IndexController( AzureCosmosFactory azureCosmosFactory ) 
+        { 
+                _azureCosmosFactory = azureCosmosFactory;
+        }
+        [HttpPost("message")]
+        public async Task<IActionResult> Message(JsonElement dto)
+        {
+            List<Teacher> teachers = new List<Teacher>();// where c.id in( '1595321354222','1607409409')
+            await foreach (var  item in _azureCosmosFactory.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher").
+                GetItemQueryIteratorSql<Teacher>(queryText: "select value c from c", requestOptions: new Microsoft.Azure.Cosmos.QueryRequestOptions() { PartitionKey= new Microsoft.Azure.Cosmos.PartitionKey("Base") }))
+            {
+                teachers.Add(item);
+            }
+            List<JsonElement> elements = new List<JsonElement>();
+            await foreach (var item in _azureCosmosFactory.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher").
+              GetItemQueryStreamIteratorSql(queryText: "select value c from c where c.id in( '1595321354222','1607409409222')", requestOptions: new Microsoft.Azure.Cosmos.QueryRequestOptions() { PartitionKey= new Microsoft.Azure.Cosmos.PartitionKey("Base") }))
+            {
+                 var json = await JsonDocument.ParseAsync(item.Content);
+                if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                {
+                    foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                    {
+                        elements.Add(obj);
+                    }
+                }
+            }
+
+            return Ok(new { response = teachers,elements });
+        }
+    }
+    public class Teacher 
+    {
+            public string id { get; set;}
+            public string name { get; set; }
+            public string code { get; set; }
+            public string pk { get; set; }
+    }
+
+}

+ 384 - 0
HTEXCosmosDB/Cosmos/AzureCosmosExtensions.cs

@@ -0,0 +1,384 @@
+using Azure;
+using Microsoft.Azure.Cosmos;
+using System.Text.Json;
+
+namespace HTEXCosmosDB
+{
+    public static class AzureCosmosExtensions
+    {
+        public static double RU(this Response response)
+        {
+            try
+            {
+                response.Headers.TryGetValue("x-ms-request-charge", out var value);
+                var ru = Convert.ToDouble(value);
+                return ru;
+            }
+            catch
+            {
+                return 0;
+            }
+        }
+
+        public static string? GetContinuationToken(this Response response)
+        {
+            try
+            {
+                response.Headers.TryGetValue("x-ms-continuation", out var value);
+                return value;
+            }
+            catch
+            {
+                return null;
+            }
+        }
+
+        //public static async IAsyncEnumerable<(List<T> list, double RU, string? continuationToken)> GetItemQueryIterator<T>(this Container container, QueryDefinition queryDefinition, QueryRequestOptions requestOptions,string? continuationToken  = null, int? pageSize = null)
+        //{
+        //    List<T> list = new List<T>();
+        //    double RU = 0;
+        //    //if (string.IsNullOrWhiteSpace(partitionkey))
+        //    //{
+        //    //    return (list, RU, continuationToken);
+        //    //}
+        //    FeedIterator<T> iterator = container.GetItemQueryIterator<T>(queryDefinition: queryDefinition, continuationToken: continuationToken, requestOptions: requestOptions);
+        //    while (iterator.HasMoreResults)
+        //    {
+        //        FeedResponse<T> currentResultSet = await iterator.ReadNextAsync();
+        //        list.AddRange(currentResultSet);
+        //        RU += currentResultSet.RequestCharge;
+        //        //此处需要优化 ,检查相关的 关键字 用正则
+        //        if (queryDefinition.QueryText.Contains(" distinct ", StringComparison.OrdinalIgnoreCase)
+        //            || (queryDefinition.QueryText.Contains("order ", StringComparison.OrdinalIgnoreCase)
+        //            && !queryDefinition.QueryText.Contains(".order ", StringComparison.OrdinalIgnoreCase)))
+        //        {
+        //            continuationToken = null;
+        //        }
+        //        else
+        //        {
+        //            continuationToken = currentResultSet.ContinuationToken;
+        //        }
+        //        if (pageSize.HasValue && pageSize.Value >= 0 && list.Count >= pageSize)
+        //        {
+        //            break;
+        //        }
+        //        yield return  (list, RU, continuationToken);
+        //    }
+           
+        //}
+
+        //public static async Task<(List<T> list, double RU, string? continuationToken)> GetList<T>(this Container container, QueryDefinition queryDefinition, string? partitionkey = null , string? continuationToken = null, int? pageSize = null)
+        //{
+        //    List<T> list = new List<T>();
+        //    double RU = 0;
+        //    //if (string.IsNullOrWhiteSpace(partitionkey))
+        //    //{
+        //    //    return (list, RU, continuationToken);
+        //    //}
+        //    FeedIterator<T> iterator = container.GetItemQueryIterator<T>(queryDefinition: queryDefinition, continuationToken: continuationToken, requestOptions: new QueryRequestOptions { MaxItemCount = pageSize, PartitionKey =!string.IsNullOrWhiteSpace(partitionkey) ? new PartitionKey(partitionkey) : null });
+        //    while (iterator.HasMoreResults)
+        //    {
+        //        FeedResponse<T> currentResultSet = await iterator.ReadNextAsync();
+        //        list.AddRange(currentResultSet);
+        //        RU += currentResultSet.RequestCharge;
+        //        //此处需要优化 ,检查相关的 关键字 用正则
+        //        if (queryDefinition.QueryText.Contains(" distinct ", StringComparison.OrdinalIgnoreCase)
+        //            || (queryDefinition.QueryText.Contains("order ", StringComparison.OrdinalIgnoreCase)
+        //            && !queryDefinition.QueryText.Contains(".order ", StringComparison.OrdinalIgnoreCase)))
+        //        {
+        //            continuationToken = null;
+        //        }
+        //        else
+        //        {
+        //            continuationToken = currentResultSet.ContinuationToken;
+        //        }
+        //        if (pageSize.HasValue && pageSize.Value >= 0 && list.Count >= pageSize)
+        //        {
+        //            break;
+        //        }
+        //    }
+        //    return (list, RU, continuationToken);
+        //}
+        public static async Task<T?> GetOne<T>(this Container container, QueryDefinition queryDefinition, string? partitionkey = null)
+        {
+            List<T?> list = new List<T?>();
+            //if (string.IsNullOrWhiteSpace(partitionkey))
+            //{
+            //    return default;
+            //}
+            FeedIterator<T> iterator = container.GetItemQueryIterator<T>(queryDefinition: queryDefinition,
+                requestOptions: new QueryRequestOptions { MaxItemCount = 2, PartitionKey =!string.IsNullOrWhiteSpace(partitionkey) ? new PartitionKey(partitionkey) : null });
+            while (iterator.HasMoreResults)
+            {
+                FeedResponse<T> currentResultSet = await iterator.ReadNextAsync();
+                list.AddRange(currentResultSet);
+            }
+            if (list.Count > 1)
+            {
+                throw new Exception("当前查询条件返回的结果不唯一");
+            }
+            else if (list.Count <= 0)
+            {
+                return default;
+            }
+            else
+            {
+                return list.First();
+            }
+        }
+
+        public static async Task<T?> GetOne<T>(this Container container, string sql, string? partitionkey = null)
+        {
+            List<T?> list = new List<T?>();
+            //if (string.IsNullOrWhiteSpace(partitionkey))
+            //{
+            //    return default;
+            //}
+            FeedIterator<T> iterator = container.GetItemQueryIterator<T>(queryText: sql,
+                 requestOptions: new QueryRequestOptions { MaxItemCount = 2, PartitionKey =!string.IsNullOrWhiteSpace(partitionkey) ? new PartitionKey(partitionkey) : null });
+            while (iterator.HasMoreResults)
+            {
+                FeedResponse<T> currentResultSet = await iterator.ReadNextAsync();
+                list.AddRange(currentResultSet);
+            }
+            if (list.Count > 1)
+            {
+                throw new Exception("当前查询条件返回的结果不唯一");
+            }
+            else if (list.Count <=0)
+            {
+                return default;
+            }
+            else
+            {
+                return list.First();
+            }
+        }
+        public static async IAsyncEnumerable<CosmosDBResult<T>> GetItemQueryIteratorList<T>(this Container container, string queryText, QueryRequestOptions? requestOptions= null,  string? continuationToken = null, int? pageSize = null)
+        {
+           
+            //if (string.IsNullOrWhiteSpace(partitionkey))
+            //{
+            //    return (new CosmosDBResult<T> { list = list, ru=RU, continuationToken=continuationToken });
+            //}
+            FeedIterator<T> iterator = container.GetItemQueryIterator<T>(queryText: queryText, continuationToken: continuationToken, requestOptions: requestOptions);
+            while (iterator.HasMoreResults)
+            {
+                List<T> list = new List<T>();
+                double RU = 0;
+                FeedResponse<T> currentResultSet = await iterator.ReadNextAsync();
+                list.AddRange(currentResultSet);
+                RU += currentResultSet.RequestCharge;
+                //此处需要优化 ,检查相关的 关键字 用正则
+                if (queryText.Contains(" distinct ", StringComparison.OrdinalIgnoreCase)
+                    || (queryText.Contains("order ", StringComparison.OrdinalIgnoreCase)
+                    && !queryText.Contains(".order ", StringComparison.OrdinalIgnoreCase)))
+                {
+                    continuationToken = null;
+                }
+                else
+                {
+                    continuationToken = currentResultSet.ContinuationToken;
+                }
+                if (pageSize.HasValue && pageSize.Value >=0 && list.Count>=pageSize)
+                {
+                    break;
+                }
+                //记录日志,RU开销大于400(开发测试),1000(正式)
+                yield  return (new CosmosDBResult<T> { list = list, ru = RU, continuationToken = continuationToken });
+            }
+           
+        }
+        public static async Task<CosmosDBResult<T>> GetList<T>(this Container container, string sql, string? partitionkey = null, string? continuationToken = null, int? pageSize = null)
+        {
+            List<T> list = new List<T>();
+            double RU = 0;
+            //if (string.IsNullOrWhiteSpace(partitionkey))
+            //{
+            //    return (new CosmosDBResult<T> { list = list, ru=RU, continuationToken=continuationToken });
+            //}
+            FeedIterator<T> iterator = container.GetItemQueryIterator<T>(queryText: sql, continuationToken: continuationToken, requestOptions: new QueryRequestOptions { MaxItemCount=pageSize, PartitionKey =!string.IsNullOrWhiteSpace(partitionkey) ? new PartitionKey(partitionkey) : null });
+            while (iterator.HasMoreResults)
+            {
+                FeedResponse<T> currentResultSet = await iterator.ReadNextAsync();
+                list.AddRange(currentResultSet);
+                RU += currentResultSet.RequestCharge;
+                //此处需要优化 ,检查相关的 关键字 用正则
+                if (sql.Contains(" distinct ", StringComparison.OrdinalIgnoreCase)
+                    || (sql.Contains("order ", StringComparison.OrdinalIgnoreCase)
+                    && !sql.Contains(".order ", StringComparison.OrdinalIgnoreCase)))
+                {
+                    continuationToken = null;
+                }
+                else
+                {
+                    continuationToken = currentResultSet.ContinuationToken;
+                }
+                if (pageSize.HasValue && pageSize.Value >=0 && list.Count>=pageSize)
+                {
+                    break;
+                }
+            }
+            //记录日志,RU开销大于400(开发测试),1000(正式)
+            return (new CosmosDBResult<T> { list = list, ru = RU, continuationToken = continuationToken }); 
+        }
+        /// <summary>
+        /// 取得当前容器指定分区键的Count数,支持SQL Where条件,不支持排序
+        /// </summary>
+        /// <param name="container"></param>
+        /// <param name="partitionkey"></param>
+        /// <param name="queryWhere"></param>
+        /// <returns></returns>
+        public static async Task<int> GetCount(this Container container, string queryWhere = "WHERE 1=1", string? partitionkey = null)
+        {
+            int totalCount = 0;
+            var items = container.GetItemQueryStreamIterator(
+                queryText: $"SELECT VALUE COUNT(1) From c {queryWhere}",
+                requestOptions: new QueryRequestOptions() { PartitionKey =!string.IsNullOrWhiteSpace(partitionkey) ? new PartitionKey(partitionkey) : null, MaxItemCount = -1 });
+            while (items.HasMoreResults)
+            {
+                using var response = await items.ReadNextAsync();
+                using var json = await JsonDocument.ParseAsync(response.Content);
+                if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                {
+                    foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                    {
+                        totalCount = obj.GetInt32();
+                    }
+                }
+            }
+
+            return totalCount;
+        }
+
+        public static async Task<ResponseMessage[]> DeleteItemsStreamAsync(this Container container, List<string> ids, string partitionkey)
+        {
+            List<Task<ResponseMessage>> responses = new List<Task<ResponseMessage>>();
+            if (ids!= null  && ids.Count > 0)
+            {
+                foreach (var id in ids)
+                {
+                    try
+                    {
+                        responses.Add(container.DeleteItemStreamAsync(id, new PartitionKey(partitionkey)));
+                    }
+                    catch
+                    {
+                        continue;
+                    }
+                }
+            }
+            var response = await Task.WhenAll(responses);
+            return response;
+        }
+
+        public static async Task<ItemResponse<T>[]> DeleteItemsAsync<T>(this Container container, List<string> ids, string partitionkey)
+        {
+            List<Task<ItemResponse<T>>> responses = new List<Task<ItemResponse<T>>>(); ;
+            if (ids!= null  && ids.Count > 0)
+            {
+                foreach (var id in ids)
+                {
+                    try
+                    {
+                        responses.Add(container.DeleteItemAsync<T>(id, new PartitionKey(partitionkey)));
+                    }
+                    catch
+                    {
+                        continue;
+                    }
+                }
+            }
+            var response = await Task.WhenAll(responses);
+            return response;
+        }
+
+        public static async IAsyncEnumerable<ResponseMessage> GetItemQueryStreamIteratorSql(this Microsoft.Azure.Cosmos.Container container, string queryText = null, string continuationToken = null, Microsoft.Azure.Cosmos.QueryRequestOptions requestOptions = null)
+        {
+            var items = container.GetItemQueryStreamIterator(
+            queryText: queryText, continuationToken: continuationToken,
+                requestOptions: requestOptions);
+            while (items.HasMoreResults)
+            {
+                ResponseMessage response = await items.ReadNextAsync();
+                if (response.IsSuccessStatusCode)
+                {
+                    yield return response;
+                }
+                else
+                {
+                    break;
+                }
+            }
+        }
+        public static async IAsyncEnumerable<ResponseMessage> GetItemQueryStreamIteratorQuery(this Microsoft.Azure.Cosmos.Container container, Microsoft.Azure.Cosmos.QueryDefinition queryDefinition, string continuationToken = null, Microsoft.Azure.Cosmos.QueryRequestOptions requestOptions = null)
+        {
+            var items = container.GetItemQueryStreamIterator(
+            queryDefinition: queryDefinition, continuationToken: continuationToken,
+            requestOptions: requestOptions);
+            while (items.HasMoreResults)
+            {
+                ResponseMessage response = await items.ReadNextAsync();
+                if (response.IsSuccessStatusCode)
+                {
+                    yield return response;
+                }
+                else {
+                    break;
+                }
+               
+            }
+        }
+
+        public static async IAsyncEnumerable<T> GetItemQueryIteratorQuery<T>(this Microsoft.Azure.Cosmos.Container container, Microsoft.Azure.Cosmos.QueryDefinition queryDefinition, string continuationToken = null, Microsoft.Azure.Cosmos.QueryRequestOptions requestOptions = null)
+        {
+            var items = container.GetItemQueryIterator<T>(
+            queryDefinition: queryDefinition, continuationToken: continuationToken,
+            requestOptions: requestOptions);
+            while (items.HasMoreResults)
+            {
+                FeedResponse<T> response = await items.ReadNextAsync();
+                if (response.Any())
+                {
+                    foreach (var rs in response)
+                    {
+                        yield return rs;
+                    }
+                }
+                else
+                {
+                    yield break;
+                }
+            }
+        }
+        public static async IAsyncEnumerable<T> GetItemQueryIteratorSql<T>(this Microsoft.Azure.Cosmos.Container container, string queryText, string continuationToken = null, Microsoft.Azure.Cosmos.QueryRequestOptions requestOptions = null)
+        {
+            var items = container.GetItemQueryIterator<T>(
+            queryText: queryText, continuationToken: continuationToken,
+            requestOptions: requestOptions);
+           
+            while (items.HasMoreResults)
+            {
+                FeedResponse<T> response = await items.ReadNextAsync();
+                if (response.Any())
+                {
+                    foreach (var rs in response) {
+                        yield return rs;
+                    }
+                }
+                else 
+                {
+                    yield break; 
+                }
+            }
+        }
+    }
+
+    public class CosmosDBResult<T>
+    {
+        public List<T>? list { get; set; } = new List<T>();
+        public string? continuationToken { get; set; }
+        //RU数据库查询开销
+        public double ru { get; set; }
+    }
+}

+ 103 - 0
HTEXCosmosDB/Cosmos/AzureCosmosFactory.cs

@@ -0,0 +1,103 @@
+using Azure.Core.Serialization;
+using Microsoft.Azure.Cosmos;
+using Microsoft.Extensions.Options;
+using System.Collections.Concurrent;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace HTEXCosmosDB
+{
+    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>();
+
+        //   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;
+        }
+
+        /// <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
+            {
+                //CosmosClientOptions 的 SerializerOptions = new CosmosSerializationOptions() { PropertyNamingPolicy = CosmosPropertyNamingPolicy.CamelCase } 
+                //需等待官方修正
+
+                JsonSerializerOptions jsonSerializerOptions = new JsonSerializerOptions()
+                {
+                    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
+                };
+                var cm = CosmosClients.GetOrAdd(name, x => new CosmosClient(_optionsMonitor.Get(name).CosmosConnectionString, new CosmosClientOptions()
+                {
+                    Serializer= new CosmosSystemTextJsonSerializer(jsonSerializerOptions),
+                    ApplicationRegion = region
+                }));
+                return cm;
+            }
+            catch (Exception e)
+            {
+                _logger?.LogWarning(e, e.Message);
+                throw;
+            }
+        }
+    }
+    /// <summary>
+    /// Uses <see cref="Azure.Core.Serialization.JsonObjectSerializer"/> which leverages System.Text.Json providing a simple API to interact with on the Azure SDKs.
+    /// </summary>
+    // <SystemTextJsonSerializer>
+    public class CosmosSystemTextJsonSerializer : CosmosSerializer
+    {
+        private readonly JsonObjectSerializer systemTextJsonSerializer;
+
+        public CosmosSystemTextJsonSerializer(JsonSerializerOptions jsonSerializerOptions)
+        {
+            this.systemTextJsonSerializer = new JsonObjectSerializer(jsonSerializerOptions);
+        }
+
+        public override T FromStream<T>(Stream stream)
+        {
+            using (stream)
+            {
+                if (stream.CanSeek
+                       && stream.Length == 0)
+                {
+                    return default;
+                }
+
+                if (typeof(Stream).IsAssignableFrom(typeof(T)))
+                {
+                    return (T)(object)stream;
+                }
+
+                return (T)this.systemTextJsonSerializer.Deserialize(stream, typeof(T), default);
+            }
+        }
+
+        public override Stream ToStream<T>(T input)
+        {
+            MemoryStream streamPayload = new MemoryStream();
+            this.systemTextJsonSerializer.Serialize(streamPayload, input, input.GetType(), default);
+            streamPayload.Position = 0;
+            return streamPayload;
+        }
+    }
+    // </SystemTextJsonSerializer>
+}
+

+ 16 - 0
HTEXCosmosDB/Cosmos/AzureCosmosFactoryExtensions.cs

@@ -0,0 +1,16 @@
+using Microsoft.Extensions.DependencyInjection.Extensions;
+
+namespace HTEXCosmosDB
+{
+    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
HTEXCosmosDB/Cosmos/AzureCosmosFactoryOptions.cs

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

+ 13 - 0
HTEXCosmosDB/HTEXCosmosDB.csproj

@@ -0,0 +1,13 @@
+<Project Sdk="Microsoft.NET.Sdk.Web">
+
+  <PropertyGroup>
+    <TargetFramework>net8.0</TargetFramework>
+    <Nullable>enable</Nullable>
+    <ImplicitUsings>enable</ImplicitUsings>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.Azure.Cosmos" Version="3.41.0" />
+  </ItemGroup>
+
+</Project>

+ 6 - 0
HTEXCosmosDB/HTEXCosmosDB.http

@@ -0,0 +1,6 @@
+@HTEXCosmosDB_HostAddress = http://localhost:5006
+
+GET {{HTEXCosmosDB_HostAddress}}/weatherforecast/
+Accept: application/json
+
+###

+ 44 - 0
HTEXCosmosDB/Program.cs

@@ -0,0 +1,44 @@
+namespace HTEXCosmosDB
+{
+    public class Program
+    {
+        public static void Main(string[] args)
+        {
+            var builder = WebApplication.CreateBuilder(args);
+
+            // Add services to the container.
+            builder.Services.AddAuthorization();
+
+            builder.Services.AddControllers();
+            builder.Services.AddEndpointsApiExplorer();
+            builder.Services.AddAzureCosmos("AccountEndpoint=https://cdhabookdep-free.documents.azure.cn:443/;AccountKey=JTUVk92Gjsx17L0xqxn0X4wX2thDPMKiw4daeTyV1HzPb6JmBeHdtFY1MF1jdctW1ofgzqkDMFOtcqS46by31A==;");
+            var app = builder.Build();
+
+            // Configure the HTTP request pipeline.
+
+            app.UseHttpsRedirection();
+
+            app.UseAuthorization();
+
+            var summaries = new[]
+            {
+                "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
+            };
+
+            app.MapGet("/weatherforecast", (HttpContext httpContext) =>
+            {
+                var forecast = Enumerable.Range(1, 5).Select(index =>
+                    new WeatherForecast
+                    {
+                        Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
+                        TemperatureC = Random.Shared.Next(-20, 55),
+                        Summary = summaries[Random.Shared.Next(summaries.Length)]
+                    })
+                    .ToArray();
+                return forecast;
+            });
+            app.MapControllers();
+            app.Run();
+        }
+    }
+}

+ 41 - 0
HTEXCosmosDB/Properties/launchSettings.json

@@ -0,0 +1,41 @@
+{
+  "$schema": "http://json.schemastore.org/launchsettings.json",
+  "iisSettings": {
+    "windowsAuthentication": false,
+    "anonymousAuthentication": true,
+    "iisExpress": {
+      "applicationUrl": "http://localhost:20886",
+      "sslPort": 44356
+    }
+  },
+  "profiles": {
+    "http": {
+      "commandName": "Project",
+      "dotnetRunMessages": true,
+      "launchBrowser": true,
+      "launchUrl": "weatherforecast",
+      "applicationUrl": "http://localhost:5006",
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    },
+    "https": {
+      "commandName": "Project",
+      "dotnetRunMessages": true,
+      "launchBrowser": true,
+      "launchUrl": "weatherforecast",
+      "applicationUrl": "https://localhost:7050;http://localhost:5006",
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    },
+    "IIS Express": {
+      "commandName": "IISExpress",
+      "launchBrowser": true,
+      "launchUrl": "weatherforecast",
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    }
+  }
+}

+ 13 - 0
HTEXCosmosDB/WeatherForecast.cs

@@ -0,0 +1,13 @@
+namespace HTEXCosmosDB
+{
+    public class WeatherForecast
+    {
+        public DateOnly Date { get; set; }
+
+        public int TemperatureC { get; set; }
+
+        public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
+
+        public string? Summary { get; set; }
+    }
+}

+ 8 - 0
HTEXCosmosDB/appsettings.Development.json

@@ -0,0 +1,8 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Information",
+      "Microsoft.AspNetCore": "Warning"
+    }
+  }
+}

+ 9 - 0
HTEXCosmosDB/appsettings.json

@@ -0,0 +1,9 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Information",
+      "Microsoft.AspNetCore": "Warning"
+    }
+  },
+  "AllowedHosts": "*"
+}

+ 15 - 1
TEAMModelHTEX.sln

@@ -37,7 +37,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AML.APP", "AML.APP\AML.APP.
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HTEX.Complex", "HTEX.Complex\HTEX.Complex.csproj", "{7FBCC897-D9C7-4B88-BB2C-90E18CB8B289}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HTEXGpt", "HTEXGpt\HTEXGpt.csproj", "{C2B6319D-E804-41DE-B48E-8555007280F9}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HTEXGpt", "HTEXGpt\HTEXGpt.csproj", "{C2B6319D-E804-41DE-B48E-8555007280F9}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HTEXCosmosDB", "HTEXCosmosDB\HTEXCosmosDB.csproj", "{2B6EB00C-C0E7-4F0C-ABDC-05D802CF272E}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -265,6 +267,18 @@ Global
 		{C2B6319D-E804-41DE-B48E-8555007280F9}.Release|iPhone.Build.0 = Release|Any CPU
 		{C2B6319D-E804-41DE-B48E-8555007280F9}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
 		{C2B6319D-E804-41DE-B48E-8555007280F9}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+		{2B6EB00C-C0E7-4F0C-ABDC-05D802CF272E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{2B6EB00C-C0E7-4F0C-ABDC-05D802CF272E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{2B6EB00C-C0E7-4F0C-ABDC-05D802CF272E}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{2B6EB00C-C0E7-4F0C-ABDC-05D802CF272E}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{2B6EB00C-C0E7-4F0C-ABDC-05D802CF272E}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{2B6EB00C-C0E7-4F0C-ABDC-05D802CF272E}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{2B6EB00C-C0E7-4F0C-ABDC-05D802CF272E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{2B6EB00C-C0E7-4F0C-ABDC-05D802CF272E}.Release|Any CPU.Build.0 = Release|Any CPU
+		{2B6EB00C-C0E7-4F0C-ABDC-05D802CF272E}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{2B6EB00C-C0E7-4F0C-ABDC-05D802CF272E}.Release|iPhone.Build.0 = Release|Any CPU
+		{2B6EB00C-C0E7-4F0C-ABDC-05D802CF272E}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{2B6EB00C-C0E7-4F0C-ABDC-05D802CF272E}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE