using System; using System.Collections.Generic; using System.Threading.Tasks; using System.Linq; using TEAMModelOS.SDK.Module.AzureCosmosDB.Configuration; using TEAMModelOS.SDK.Module.AzureCosmosDB.Interfaces; using Microsoft.Azure.Documents.Client; using Microsoft.Azure.Documents; using TEAMModelOS.SDK.Helper.Security.AESCrypt; using TEAMModelOS.SDK.Context.Exception; using Microsoft.Azure.Documents.Linq; using TEAMModelOS.SDK.Helper.Query.LinqHelper; using System.Reflection; using Microsoft.Azure.Cosmos; using Microsoft.Azure.CosmosDB.BulkExecutor; using Microsoft.Azure.CosmosDB.BulkExecutor.BulkImport; using System.Threading; using TEAMModelOS.SDK.Helper.Common.JsonHelper; using Microsoft.Azure.CosmosDB.BulkExecutor.BulkUpdate; using TEAMModelOS.SDK.Helper.Common.CollectionHelper; using Microsoft.Azure.CosmosDB.BulkExecutor.BulkDelete; using TEAMModelOS.SDK.Context.Attributes.Azure; using System.Text; using TEAMModelOS.SDK.Helper.Common.ReflectorExtensions; using Microsoft.AspNetCore.Hosting; using System.Collections.Concurrent; using DataType = Microsoft.Azure.Documents.DataType; using RequestOptions = Microsoft.Azure.Documents.Client.RequestOptions; using PartitionKey = Microsoft.Azure.Documents.PartitionKey; using Newtonsoft.Json.Linq; namespace TEAMModelOS.SDK.Module.AzureCosmosDB.Implements { /// /// sdk 文档https://github.com/Azure/azure-cosmos-dotnet-v2/tree/master/samples /// https://github.com/Azure/azure-cosmos-dotnet-v2/blob/530c8d9cf7c99df7300246da05206c57ce654233/samples/code-samples/DatabaseManagement/Program.cs#L72-L121 /// public class AzureCosmosDBRepository : IAzureCosmosDBRepository { /// /// sdk 文档https://github.com/Azure/azure-cosmos-dotnet-v2/tree/master/samples /// https://github.com/Azure/azure-cosmos-dotnet-v2/blob/530c8d9cf7c99df7300246da05206c57ce654233/samples/code-samples/DatabaseManagement/Program.cs#L72-L121 /// private DocumentClient CosmosClient { get; set; } /// /// 线程安全的dict类型 /// private ConcurrentDictionary DocumentCollectionDict { get; set; } = new ConcurrentDictionary(); // private DocumentCollection CosmosCollection { get; set; } private string Database { get; set; } private int CollectionThroughput { get; set; } public AzureCosmosDBRepository(AzureCosmosDBOptions options) { try { if (!string.IsNullOrEmpty(options.ConnectionString)) { CosmosClient = CosmosDBClientSingleton.getInstance(options.ConnectionString, options.ConnectionKey).GetCosmosDBClient(); } else { throw new BizException("请设置正确的AzureCosmosDB数据库配置信息!"); } Database = options.Database; CollectionThroughput = options.CollectionThroughput; CosmosClient.CreateDatabaseIfNotExistsAsync(new Microsoft.Azure.Documents.Database { Id = Database }); // _connectionString = options.ConnectionString; // CosmosSerializer //获取数据库所有的表 Microsoft.Azure.Documents.Client.FeedResponse collections = CosmosClient.ReadDocumentCollectionFeedAsync(UriFactory.CreateDatabaseUri(Database)).GetAwaiter().GetResult(); foreach (IGrouping group in collections.GroupBy(c => c.Id)) { DocumentCollectionDict.TryAdd(group.Key, group.First()); } //collections List types = ReflectorExtensions.GetAllTypeAsAttribute(options.ScanModel); foreach (Type type in types) { string PartitionKey = GetPartitionKey(type); string CollectionName = ""; int RU = 0; IEnumerable attributes = type.GetCustomAttributes(true); if (!string.IsNullOrEmpty(attributes.First().Name)) { CollectionName = attributes.First().Name; } else { CollectionName = type.Name; } if (attributes.First().RU > 400) { RU = attributes.First().RU; } else { RU = options.CollectionThroughput; } //如果表存在于数据则检查RU是否变动,如果不存在则执行创建DocumentCollection if (DocumentCollectionDict.TryGetValue(CollectionName, out DocumentCollection collection)) { Offer offer = CosmosClient.CreateOfferQuery().Where(o => o.ResourceLink == collection.SelfLink).AsEnumerable().Single(); OfferV2 offerV2 = (OfferV2)offer; //更新RU if (offerV2.Content.OfferThroughput < RU) { CosmosClient.ReplaceOfferAsync(new OfferV2(offer, RU)); } } else { DocumentCollection collectionDefinition = new DocumentCollection { Id = CollectionName }; collectionDefinition.IndexingPolicy = new Microsoft.Azure.Documents.IndexingPolicy(new RangeIndex(DataType.String) { Precision = -1 }); // collectionDefinition.PartitionKey = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection() }; if (!string.IsNullOrEmpty(PartitionKey)) { collectionDefinition.PartitionKey.Paths.Add("/" + PartitionKey); } // CosmosCollection = await this.CosmosClient.CreateDocumentCollectionIfNotExistsAsync(UriFactory.CreateDatabaseUri(Database), collectionDefinition); if (RU > CollectionThroughput) { CollectionThroughput = RU; } DocumentCollection DocumentCollection = CosmosClient.CreateDocumentCollectionIfNotExistsAsync( UriFactory.CreateDatabaseUri(Database), collectionDefinition, new Microsoft.Azure.Documents.Client.RequestOptions { OfferThroughput = CollectionThroughput }).GetAwaiter().GetResult(); DocumentCollectionDict.TryAdd(CollectionName, DocumentCollection); } } } catch (DocumentClientException de) { Exception baseException = de.GetBaseException(); //Console.WriteLine("{0} error occurred: {1}, Message: {2}", de.StatusCode, de.Message, baseException.Message); } catch (Exception e) { Exception baseException = e.GetBaseException(); //Console.WriteLine("Error: {0}, Message: {1}", e.Message, baseException.Message); } finally { // Console.WriteLine("End of demo, press any key to exit."); // Console.ReadKey(); } } private async Task InitializeCollection() { Type type = typeof(T); string partitionKey = GetPartitionKey(); string CollectionName; IEnumerable attributes = type.GetCustomAttributes(true); if (!string.IsNullOrEmpty(attributes.First().Name)) { CollectionName = attributes.First().Name; } else { CollectionName = type.Name; } return await InitializeCollection(CollectionName, partitionKey); } private async Task InitializeCollection(string CollectionName, string PartitionKey) { /////内存中已经存在这个表则直接返回 if (DocumentCollectionDict.TryGetValue(CollectionName, out DocumentCollection DocumentCollection)) { return DocumentCollection; }///如果没有则尝试默认创建 else { DocumentCollection documentCollection = new DocumentCollection { Id = CollectionName }; documentCollection.IndexingPolicy = new Microsoft.Azure.Documents.IndexingPolicy(new RangeIndex(DataType.String) { Precision = -1 }); // collectionDefinition.PartitionKey = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection() }; if (!string.IsNullOrEmpty(PartitionKey)) { documentCollection.PartitionKey.Paths.Add("/" + PartitionKey); } // CosmosCollection = await this.CosmosClient.CreateDocumentCollectionIfNotExistsAsync(UriFactory.CreateDatabaseUri(Database), collectionDefinition); documentCollection = await this.CosmosClient.CreateDocumentCollectionIfNotExistsAsync( UriFactory.CreateDatabaseUri(Database), documentCollection, new RequestOptions { OfferThroughput = CollectionThroughput }); DocumentCollectionDict.TryAdd(CollectionName, documentCollection); return documentCollection; } } private string GetPartitionKey() { Type type = typeof(T); return GetPartitionKey(type); } private string GetPartitionKey(Type type) { PropertyInfo[] properties = type.GetProperties(); List attrProperties = new List(); 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("PartitionKey can only be single!"); } } } public async Task Save(T entity) //where T : object, new() { try { Type t = typeof(T); DocumentCollection collection= await InitializeCollection(); ResourceResponse doc = await CosmosClient.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri(Database, collection.Id), entity); //Console.WriteLine(doc.ActivityId); return entity; } catch (Exception e) { throw new BizException(e.Message); } } public async Task Update(T entity) { Type t = typeof(T); DocumentCollection collection = await InitializeCollection(); ResourceResponse doc = await CosmosClient.UpsertDocumentAsync(UriFactory.CreateDocumentCollectionUri(Database, collection.Id), entity); return entity; } public async Task ReplaceObject(T entity, string key) { Type t = typeof(T); DocumentCollection collection = await InitializeCollection(); try { ResourceResponse doc = await CosmosClient.ReplaceDocumentAsync(UriFactory.CreateDocumentUri(Database,collection.Id, key), entity); return key; } catch (Exception e) { Console.WriteLine("{0} Exception caught.", e); //return false; } return null; } public async Task ReplaceObject(T entity, string key, string partitionKey) { Type t = typeof(T); DocumentCollection collection = await InitializeCollection(); try { ResourceResponse doc = await CosmosClient.ReplaceDocumentAsync(UriFactory.CreateDocumentUri(Database,collection.Id, key), entity, new RequestOptions { PartitionKey = new PartitionKey(partitionKey) }); return key; } catch (Exception e) { throw new BizException(e.Message); //Console.WriteLine("{0} Exception caught.", e); //return false; } } public async Task> FindAll() { Type t = typeof(T); Boolean open = true; List objs = new List(); DocumentCollection collection = await InitializeCollection(); //查询条数 -1是全部 FeedOptions queryOptions = new FeedOptions { MaxItemCount = -1, EnableCrossPartitionQuery = open }; var query = CosmosClient.CreateDocumentQuery(UriFactory.CreateDocumentCollectionUri(Database,collection.Id), queryOptions).AsDocumentQuery(); while (query.HasMoreResults) { foreach (T obj in await query.ExecuteNextAsync()) { objs.Add(obj); } } return objs; //return CosmosClient.CreateDocumentQuery(UriFactory.CreateDocumentCollectionUri(Database, t.Name),sql); } public async Task> FindLinq(Func, object> singleOrDefault) { Type t = typeof(T); List objs = new List(); DocumentCollection collection = await InitializeCollection(); //查询条数 -1是全部 FeedOptions queryOptions = new FeedOptions { MaxItemCount = -1 }; var query = CosmosClient.CreateDocumentQuery(UriFactory.CreateDocumentCollectionUri(Database, collection.Id), queryOptions); // query.Where(); return objs; //return CosmosClient.CreateDocumentQuery(UriFactory.CreateDocumentCollectionUri(Database, t.Name),sql); } public async Task> FindSQL(string sql) { Type t = typeof(T); //List objs = new List(); DocumentCollection collection = await InitializeCollection(); var query = CosmosClient.CreateDocumentQuery(UriFactory.CreateDocumentCollectionUri(Database,collection.Id), sql); //foreach (var item in query) //{ // objs.Add(item); //} return query.ToList(); } public async Task> FindSQL(string sql, bool IsPk) { Type t = typeof(T); //List objs = new List(); // Boolean open = IsPk; DocumentCollection collection = await InitializeCollection(); //查询条数 -1是全部 FeedOptions queryOptions = new FeedOptions { MaxItemCount = -1, EnableCrossPartitionQuery = IsPk }; var query = CosmosClient.CreateDocumentQuery(UriFactory.CreateDocumentCollectionUri(Database, collection.Id), sql, queryOptions); //foreach (var item in query) //{ // objs.Add(item); //} return query.ToList(); } public async Task> FindByParams(Dictionary dict) { DocumentCollection collection = await InitializeCollection(); Type t = typeof(T); Boolean open = true; List filters = new List(); string PKname = ""; PropertyInfo[] properties = t.GetProperties(); foreach (PropertyInfo property in properties) { object[] attributes = property.GetCustomAttributes(true); foreach (object attribute in attributes) //2.通过映射,找到成员属性上关联的特性类实例, { if (attribute is PartitionKeyAttribute) { PKname = property.Name; break; } } } foreach (string key in dict.Keys) { //if (t.Name.Equals(key)) { // open = false; //} if (PKname.Equals(key)) { open = false; } filters.Add(new Filter { Contrast = "and", Key = key, Value = dict[key] != null ? dict[key].ToString() : throw new Exception("参数值不能为null") }); } //List objs = new List(); await InitializeCollection(); //查询条数 -1是全部 FeedOptions queryOptions = new FeedOptions { MaxItemCount = -1, EnableCrossPartitionQuery = open }; var query = CosmosClient.CreateDocumentQuery(UriFactory.CreateDocumentCollectionUri(Database, collection.Id), queryOptions); List list = DynamicLinq.GenerateFilter(query, filters).ToList(); return list; //return CosmosClient.CreateDocumentQuery(UriFactory.CreateDocumentCollectionUri(Database, t.Name),sql); } public async Task DeleteAsync(string id) { Type t = typeof(T); DocumentCollection collection = await InitializeCollection(); ResourceResponse doc = await CosmosClient.DeleteDocumentAsync(UriFactory.CreateDocumentUri(Database,collection.Id, id)); //Console.WriteLine(doc.ActivityId); return id; } public async Task DeleteAsync(T entity) { DocumentCollection collection = await InitializeCollection(); Type t = typeof(T); string PartitionKey = GetPartitionKey(); if (!string.IsNullOrEmpty(PartitionKey)) { string pkValue = entity.GetType().GetProperty(PartitionKey).GetValue(entity).ToString(); string idValue = entity.GetType().GetProperty("id").GetValue(entity).ToString(); ResourceResponse doc = await CosmosClient.DeleteDocumentAsync(UriFactory.CreateDocumentUri(Database, collection.Id, idValue), new RequestOptions { PartitionKey = new PartitionKey(pkValue) }); } else { string idValue = entity.GetType().GetProperty("id").GetValue(entity).ToString(); ResourceResponse doc = await CosmosClient.DeleteDocumentAsync(UriFactory.CreateDocumentUri(Database, collection.Id, idValue)); } //Console.WriteLine(doc.ActivityId); return entity; } public async Task DeleteAsync(string id, string partitionKey) { Type t = typeof(T); DocumentCollection collection = await InitializeCollection(); ResourceResponse doc = await CosmosClient.DeleteDocumentAsync(UriFactory.CreateDocumentUri(Database, collection.Id, id), new RequestOptions { PartitionKey = new PartitionKey(partitionKey) }); //Console.WriteLine(doc.ActivityId); return id; } public async Task> SaveAll(List enyites) { DocumentCollection dataCollection = await InitializeCollection(); // Set retry options high for initialization (default values). CosmosClient.ConnectionPolicy.RetryOptions.MaxRetryWaitTimeInSeconds = 30; CosmosClient.ConnectionPolicy.RetryOptions.MaxRetryAttemptsOnThrottledRequests = 9; IBulkExecutor bulkExecutor = new BulkExecutor(CosmosClient, dataCollection); await bulkExecutor.InitializeAsync(); // Set retries to 0 to pass control to bulk executor. CosmosClient.ConnectionPolicy.RetryOptions.MaxRetryWaitTimeInSeconds = 0; CosmosClient.ConnectionPolicy.RetryOptions.MaxRetryAttemptsOnThrottledRequests = 0; BulkImportResponse bulkImportResponse = null; long totalNumberOfDocumentsInserted = 0; double totalRequestUnitsConsumed = 0; double totalTimeTakenSec = 0; var tokenSource = new CancellationTokenSource(); var token = tokenSource.Token; int pageSize = 100; int pages = (int)Math.Ceiling((double)enyites.Count / pageSize); for (int i = 0; i < pages; i++) { List documentsToImportInBatch = new List(); List lists = enyites.Skip((i) * pageSize).Take(pageSize).ToList(); for (int j = 0; j < lists.Count; j++) { documentsToImportInBatch.Add(lists[j].ToJson()); } var tasks = new List { Task.Run(async () => { do { //try //{ bulkImportResponse = await bulkExecutor.BulkImportAsync( documents: documentsToImportInBatch, enableUpsert: true, disableAutomaticIdGeneration: true, maxConcurrencyPerPartitionKeyRange: null, maxInMemorySortingBatchSize: null, cancellationToken: token); //} //catch (DocumentClientException de) //{ // break; //} //catch (Exception e) //{ // break; //} } while (bulkImportResponse.NumberOfDocumentsImported < documentsToImportInBatch.Count); totalNumberOfDocumentsInserted += bulkImportResponse.NumberOfDocumentsImported; totalRequestUnitsConsumed += bulkImportResponse.TotalRequestUnitsConsumed; totalTimeTakenSec += bulkImportResponse.TotalTimeTaken.TotalSeconds; }, token) }; await Task.WhenAll(tasks); } return enyites; } public async Task> UpdateAll(Dictionary dict, Dictionary updateFilters, List deleteKeys = null) { DocumentCollection dataCollection = await InitializeCollection(); IBulkExecutor bulkExecutor = new BulkExecutor(CosmosClient, dataCollection); await bulkExecutor.InitializeAsync(); BulkUpdateResponse bulkUpdateResponse = null; long totalNumberOfDocumentsUpdated = 0; double totalRequestUnitsConsumed = 0; double totalTimeTakenSec = 0; var tokenSource = new CancellationTokenSource(); var token = tokenSource.Token; // Generate update operations. List updateOperations = new List(); // Unset the description field. if (null != updateFilters && updateFilters.Count > 0) { var keys = updateFilters.Keys; foreach (string key in keys) { // updateOperations.Add(new SetUpdateOperation()) if (updateFilters[key] != null && !string.IsNullOrEmpty(updateFilters[key].ToString())) { updateOperations.Add(SwitchType(key, updateFilters[key])); } } } if (deleteKeys.IsNotEmpty()) { foreach (string key in deleteKeys) { updateOperations.Add(new UnsetUpdateOperation(key)); } } List list = await FindByParams(dict); int pageSize = 100; int pages = (int)Math.Ceiling((double)list.Count / pageSize); string partitionKey = "/" + GetPartitionKey(); Type type = typeof(T); for (int i = 0; i < pages; i++) { List updateItemsInBatch = new List(); List lists = list.Skip((i) * pageSize).Take(pageSize).ToList(); for (int j = 0; j < lists.Count; j++) { string partitionKeyValue = lists[j].GetType().GetProperty(partitionKey).GetValue(lists[j]) + ""; string id = lists[j].GetType().GetProperty("id").GetValue(lists[j]) + ""; updateItemsInBatch.Add(new UpdateItem(id, partitionKeyValue, updateOperations)); } var tasks = new List { Task.Run(async () => { do { //try //{ bulkUpdateResponse = await bulkExecutor.BulkUpdateAsync( updateItems: updateItemsInBatch, maxConcurrencyPerPartitionKeyRange: null, cancellationToken: token); //} //catch (DocumentClientException de) //{ // break; //} //catch (Exception e) //{ // break; //} } while (bulkUpdateResponse.NumberOfDocumentsUpdated < updateItemsInBatch.Count); totalNumberOfDocumentsUpdated += bulkUpdateResponse.NumberOfDocumentsUpdated; totalRequestUnitsConsumed += bulkUpdateResponse.TotalRequestUnitsConsumed; totalTimeTakenSec += bulkUpdateResponse.TotalTimeTaken.TotalSeconds; }, token) }; await Task.WhenAll(tasks); } return list; } public async Task> DeleteAll(Dictionary dict) { DocumentCollection dataCollection = await InitializeCollection(); List list = await FindByParams(dict); List> pkIdTuplesToDelete = new List>(); if (list.IsNotEmpty()) { foreach (T t in list) { string id = t.GetType().GetProperty("id").GetValue(t) + ""; pkIdTuplesToDelete.Add(new Tuple(id, id)); } } else { return null; } long totalNumberOfDocumentsDeleted = 0; double totalRequestUnitsConsumed = 0; double totalTimeTakenSec = 0; BulkDeleteResponse bulkDeleteResponse = null; BulkExecutor bulkExecutor = new BulkExecutor(CosmosClient, dataCollection); await bulkExecutor.InitializeAsync(); bulkDeleteResponse = await bulkExecutor.BulkDeleteAsync(pkIdTuplesToDelete); totalNumberOfDocumentsDeleted = bulkDeleteResponse.NumberOfDocumentsDeleted; totalRequestUnitsConsumed = bulkDeleteResponse.TotalRequestUnitsConsumed; totalTimeTakenSec = bulkDeleteResponse.TotalTimeTaken.TotalSeconds; return list; } private static UpdateOperation SwitchType(string key, object obj) { Type s = obj.GetType(); TypeCode typeCode = Type.GetTypeCode(s); return typeCode switch { TypeCode.String => new SetUpdateOperation(key, obj.ToString()), TypeCode.Int32 => new SetUpdateOperation(key, (Int32)obj), TypeCode.Double => new SetUpdateOperation(key, (Double)obj), TypeCode.Byte => new SetUpdateOperation(key, (Byte)obj), TypeCode.Boolean => new SetUpdateOperation(key, (Boolean)obj), TypeCode.DateTime => new SetUpdateOperation(key, (DateTime)obj), TypeCode.Int64 => new SetUpdateOperation(key, (Int64)obj), _ => null, }; } public async Task> FindByDict(Dictionary dict, bool IsPk=true) { Type t = typeof(T); // List objs = new List(); DocumentCollection collection= await InitializeCollection(); StringBuilder sql = new StringBuilder("select * from c where 1=1 "); if (dict != null) { foreach (string key in dict.Keys) { sql.Append(GenSql(dict[key], key)); } } //查询条数 -1是全部 FeedOptions queryOptions = new FeedOptions { MaxItemCount = -1, EnableCrossPartitionQuery = IsPk }; var query = CosmosClient.CreateDocumentQuery(UriFactory.CreateDocumentCollectionUri(Database, collection.Id), sql.ToString(), queryOptions); //foreach (var item in query) //{ // objs.Add(item); //} return query.ToList(); } private static string GenSql(object obj, string key) { if (obj is JArray array) { StringBuilder sql = new StringBuilder(" and c." + key + " in ("); foreach (JValue obja in array) { if (obja.Value is string a) { sql.Append("'" + a + "',"); } if (obja.Value is int b) { sql.Append(b + ","); } if (obja.Value is double c) { sql.Append(c + ","); } if (obja.Value is bool d) { sql.Append(d + ","); } if (obja.Value is long e) { sql.Append(e + ","); } if (obja.Value is DateTime f) { sql.Append(f + ","); } } string sqls= sql.ToString().Substring(0, sql.Length - 1); sqls += ") "; return sqls; } else { Type s = obj.GetType(); TypeCode typeCode = Type.GetTypeCode(s); return typeCode switch { TypeCode.String => " and c." + key + "=" + "'" + obj.ToString() + "'", TypeCode.Int32 => " and c." + key + "=" + int.Parse(obj.ToString()), TypeCode.Double => " and c." + key + "=" + double.Parse(obj.ToString()), //case TypeCode.Byte: return "and c." + key + "=" + (Byte)obj ; TypeCode.Boolean => " and c." + key + "=" + bool.Parse(obj.ToString()), TypeCode.DateTime => " and c." + key + "=" + (DateTime)obj, TypeCode.Int64 => " and c." + key + "=" + long.Parse(obj.ToString()), _ => null, }; } } public IQueryable FindByDict(string CollectionName, Dictionary dict) { if (DocumentCollectionDict.TryGetValue(CollectionName, out DocumentCollection collection)) { // collection = await InitializeCollection(CollectionName, ""); /* StringBuilder sql = new StringBuilder("select * from " + CollectionName + " c where 1=1 "); if (dict != null) { foreach (string key in dict.Keys) { sql.Append(GenSql(dict[key], key)); } }*/ StringBuilder sql = new StringBuilder("select value(c) from c"); if (dict != null) { string Join = " join "; string instring = "in "; Dictionary keyValues = new Dictionary(); StringBuilder ps = new StringBuilder(); int heada = 0; string[] sqlHead = new string[] { "A", "B", "C", "D", "E", "F" }; int kslength = 0; foreach (KeyValuePair item in dict) { int index = 0; string[] ks = item.Key.Split("[*]"); if (ks.Length > 1) { kslength += ks.Length; if (kslength < (7 + heada)) { StringBuilder sqlitem = new StringBuilder(); for (int i = 0; i < ks.Length - 1; i++) { //Console.WriteLine(ks[i]); if (i == 0) { sqlitem.Append(Join); string a = sqlHead[heada] + index; sqlitem.Append(a + " "); //keyValues.Add(ks[i], a); keyValues[ks[i]] = a; sqlitem.Append(instring); sqlitem.Append("c."); sqlitem.Append(ks[i]); } else { sqlitem.Append(Join + " "); string a = sqlHead[heada] + index; sqlitem.Append(a + " "); //keyValues.Add(ks[i], a); keyValues[ks[i]] = a; sqlitem.Append(instring); sqlitem.Append(keyValues[ks[i - 1]]); sqlitem.Append(ks[i]); } index += 1; } // Console.WriteLine(sqlitem); sql.Append(sqlitem); string s; s = "and " + sqlHead[heada] + (ks.Length - 2) + ks[index] + " = " + "\"" + item.Value.ToString() + "\""; ps.Append(s); } else { throw new BizException("数组总共深度不能超过5层",ResponseCode.PARAMS_ERROR); } } else { ps.Append(GenSql(dict[item.Key], item.Key)); } heada += 1; } sql.Append(" where 1=1 ").Append(ps); } FeedOptions queryOptions; if (collection.PartitionKey.Paths.Count > 0) { queryOptions = new FeedOptions { MaxItemCount = -1, EnableCrossPartitionQuery = true }; } else { queryOptions = new FeedOptions { MaxItemCount = -1, EnableCrossPartitionQuery = false }; } //查询条数 -1是全部 var query = CosmosClient.CreateDocumentQuery(UriFactory.CreateDocumentCollectionUri(Database, CollectionName), sql.ToString(), queryOptions); return query; } else { throw new BizException("CollectionName named:" + CollectionName + " dose not exsit in Database!"); } } } }