AzureCosmosDBRepository.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading.Tasks;
  4. using System.Linq;
  5. using TEAMModelOS.SDK.Module.AzureCosmosDB.Configuration;
  6. using TEAMModelOS.SDK.Module.AzureCosmosDB.Interfaces;
  7. using Microsoft.Azure.Documents.Client;
  8. using Microsoft.Azure.Documents;
  9. using TEAMModelOS.SDK.Helper.Security.AESCrypt;
  10. using TEAMModelOS.SDK.Context.Exception;
  11. using Microsoft.Azure.Documents.Linq;
  12. using TEAMModelOS.SDK.Helper.Query.LinqHelper;
  13. using System.Reflection;
  14. using TEAMModelOS.SDK.Context.Attributes.Table;
  15. namespace TEAMModelOS.SDK.Module.AzureCosmosDB.Implements
  16. {
  17. /// <summary>
  18. /// sdk 文档https://github.com/Azure/azure-cosmos-dotnet-v2/tree/master/samples
  19. /// https://github.com/Azure/azure-cosmos-dotnet-v2/blob/530c8d9cf7c99df7300246da05206c57ce654233/samples/code-samples/DatabaseManagement/Program.cs#L72-L121
  20. /// </summary>
  21. public class AzureCosmosDBRepository : IAzureCosmosDBRepository
  22. {
  23. private readonly string china_con = "417A7572654368696E6120202020202020202020202020202020202020202020D63873D37F845F9DC7607B4DF4787EE26598454CE32FB5F2EE778A34A5015736196DF7940C67A034CDD4C4B44CD37C20";
  24. private readonly string china_key = "417A7572654368696E61202020202020202020202020202020202020202020203CAA1DF7E3203F0ABCB2D60C1F3DCB6D90676C4D5467167F6E6A2CB3DDE975EA37B06BBAE6E012936BEDB6D5D60B28B13642F755CB25D1958BE5366EA20FA7C47E04A67B6A96111C61C3270CD0E5539CA45E3A77A6B483F47419BBAEDE75C0F6";
  25. private readonly string global_con = "417A757265476C6F62616C2020202020202020202020202020202020202020200E357979CB69243DBF4E41BF5526830F89AB746007AC68A3DD3F9CFDA781509F1C48B2359120A5E58B8C7B1EDAA99DEA";
  26. private readonly string global_key = "417A757265476C6F62616C2020202020202020202020202020202020202020209FF199D61813D1F4857D55CFB0A7D6A797FECF39A7F47553E9C1AF23674CB04BA95748A4A3C07B90F32E5EF26E0982DBF90001E066432075C434351D73FB387D27A50716D90F414F34A4579D846C27804F658705C05A7224EC4D695FD7A5EE23";
  27. private DocumentClient CosmosClient { get; set; }
  28. private DocumentCollection CosmosCollection { get; set; }
  29. private string _Database { get; set; }
  30. public AzureCosmosDBRepository(AzureCosmosDBOptions options)
  31. {
  32. try
  33. {
  34. if (!string.IsNullOrEmpty(options.ConnectionString))
  35. {
  36. CosmosClient = CosmosDBClientSingleton.getInstance(options.ConnectionString, options.ConnectionKey).GetCosmosDBClient();
  37. }
  38. else if (AzureCosmosDBConfig.AZURE_CHINA.Equals(options.AzureTableDialect))
  39. {
  40. AESCrypt crypt = new AESCrypt();
  41. CosmosClient = CosmosDBClientSingleton.getInstance(crypt.Decrypt(china_con, options.AzureTableDialect), crypt.Decrypt(china_key, options.AzureTableDialect)).GetCosmosDBClient();
  42. }
  43. else if (AzureCosmosDBConfig.AZURE_GLOBAL.Equals(options.AzureTableDialect))
  44. {
  45. AESCrypt crypt = new AESCrypt();
  46. CosmosClient = CosmosDBClientSingleton.getInstance(crypt.Decrypt(global_con, options.AzureTableDialect), crypt.Decrypt(global_key, options.AzureTableDialect)).GetCosmosDBClient();
  47. }
  48. else
  49. {
  50. throw new BizException("请设置正确的AzureCosmosDB数据库配置信息!");
  51. }
  52. _Database = options.Database;
  53. CosmosClient.CreateDatabaseIfNotExistsAsync(new Database { Id = _Database });
  54. // _connectionString = options.ConnectionString;
  55. }
  56. catch (DocumentClientException de)
  57. {
  58. Exception baseException = de.GetBaseException();
  59. Console.WriteLine("{0} error occurred: {1}, Message: {2}", de.StatusCode, de.Message, baseException.Message);
  60. }
  61. catch (Exception e)
  62. {
  63. Exception baseException = e.GetBaseException();
  64. Console.WriteLine("Error: {0}, Message: {1}", e.Message, baseException.Message);
  65. }
  66. finally
  67. {
  68. Console.WriteLine("End of demo, press any key to exit.");
  69. // Console.ReadKey();
  70. }
  71. }
  72. private async Task<DocumentCollection> InitializeCollection<T>()
  73. {
  74. Type t = typeof(T);
  75. if (CosmosCollection == null || !CosmosCollection.Id.Equals(t.Name))
  76. {
  77. DocumentCollection collectionDefinition = new DocumentCollection { Id = t.Name };
  78. collectionDefinition.IndexingPolicy = new IndexingPolicy(new RangeIndex(DataType.String) { Precision = -1 });
  79. string partitionKey = GetPartitionKey<T>();
  80. // collectionDefinition.PartitionKey = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection<string>() };
  81. if (!string.IsNullOrEmpty(partitionKey))
  82. {
  83. collectionDefinition.PartitionKey.Paths.Add("/" + partitionKey);
  84. }
  85. CosmosCollection = await this.CosmosClient.CreateDocumentCollectionIfNotExistsAsync(UriFactory.CreateDatabaseUri(_Database), collectionDefinition);
  86. }
  87. return CosmosCollection;
  88. }
  89. private string GetPartitionKey<T>()
  90. {
  91. Type type = typeof(T);
  92. PropertyInfo[] properties = type.GetProperties();
  93. List<PropertyInfo> attrProperties = new List<PropertyInfo>();
  94. foreach (PropertyInfo property in properties)
  95. {
  96. object[] attributes = property.GetCustomAttributes(true);
  97. foreach (object attribute in attributes) //2.通过映射,找到成员属性上关联的特性类实例,
  98. {
  99. if (attribute is PartitionAttribute)
  100. {
  101. attrProperties.Add(property);
  102. }
  103. }
  104. }
  105. if (attrProperties.Count <= 0)
  106. {
  107. return null;
  108. }
  109. else
  110. {
  111. if (attrProperties.Count == 1)
  112. {
  113. return attrProperties[0].Name;
  114. }
  115. else { throw new BizException("PartitionKey can only be single!"); }
  116. }
  117. }
  118. public async Task<T> Save<T>(T entity) //where T : object, new()
  119. {
  120. Type t = typeof(T);
  121. DocumentCollection documentCollection = await InitializeCollection<T>();
  122. ResourceResponse<Document> doc =
  123. await CosmosClient.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri(_Database, t.Name), entity);
  124. //Console.WriteLine(doc.ActivityId);
  125. return entity;
  126. }
  127. public async Task<T> Update<T>(T entity)
  128. {
  129. Type t = typeof(T);
  130. await InitializeCollection<T>();
  131. ResourceResponse<Document> doc =
  132. await CosmosClient.UpsertDocumentAsync(UriFactory.CreateDocumentCollectionUri(_Database, t.Name), entity);
  133. return entity;
  134. }
  135. public async Task<string> ReplaceObject<T>(T entity, string key)
  136. {
  137. Type t = typeof(T);
  138. await InitializeCollection<T>();
  139. try
  140. {
  141. ResourceResponse<Document> doc =
  142. await CosmosClient.ReplaceDocumentAsync(UriFactory.CreateDocumentUri(_Database, t.Name, key), entity);
  143. return key;
  144. }
  145. catch (Exception e)
  146. {
  147. Console.WriteLine("{0} Exception caught.", e);
  148. //return false;
  149. }
  150. return null;
  151. }
  152. public async Task<List<T>> FindAll<T>()
  153. {
  154. Type t = typeof(T);
  155. Boolean open = true;
  156. List<T> objs = new List<T>();
  157. //await InitializeCollection<T>();
  158. //查询条数 -1是全部
  159. FeedOptions queryOptions = new FeedOptions { MaxItemCount = -1, EnableCrossPartitionQuery = open };
  160. var query = CosmosClient.CreateDocumentQuery<T>(UriFactory.CreateDocumentCollectionUri(_Database, t.Name), queryOptions).AsDocumentQuery();
  161. while (query.HasMoreResults)
  162. {
  163. foreach (T obj in await query.ExecuteNextAsync())
  164. {
  165. objs.Add(obj);
  166. }
  167. }
  168. return objs;
  169. //return CosmosClient.CreateDocumentQuery<T>(UriFactory.CreateDocumentCollectionUri(_Database, t.Name),sql);
  170. }
  171. public async Task<List<T>> FindLinq<T>(Func<IQueryable<object>, object> singleOrDefault)
  172. {
  173. Type t = typeof(T);
  174. List<T> objs = new List<T>();
  175. await InitializeCollection<T>();
  176. //查询条数 -1是全部
  177. FeedOptions queryOptions = new FeedOptions { MaxItemCount = -1 };
  178. var query = CosmosClient.CreateDocumentQuery<T>(UriFactory.CreateDocumentCollectionUri(_Database, t.Name), queryOptions);
  179. // query.Where();
  180. return objs;
  181. //return CosmosClient.CreateDocumentQuery<T>(UriFactory.CreateDocumentCollectionUri(_Database, t.Name),sql);
  182. }
  183. public async Task<List<T>> FindSQL<T>(string sql)
  184. {
  185. Type t = typeof(T);
  186. List<T> objs = new List<T>();
  187. await InitializeCollection<T>();
  188. var query = CosmosClient.CreateDocumentQuery<T>(UriFactory.CreateDocumentCollectionUri(_Database, t.Name), sql);
  189. foreach (var item in query)
  190. {
  191. objs.Add(item);
  192. }
  193. return objs;
  194. }
  195. public async Task<List<T>> FindSQL<T>(string sql, bool IsPk)
  196. {
  197. Type t = typeof(T);
  198. List<T> objs = new List<T>();
  199. Boolean open = IsPk;
  200. await InitializeCollection<T>();
  201. //查询条数 -1是全部
  202. FeedOptions queryOptions = new FeedOptions { MaxItemCount = -1, EnableCrossPartitionQuery = open };
  203. var query = CosmosClient.CreateDocumentQuery<T>(UriFactory.CreateDocumentCollectionUri(_Database, t.Name), sql, queryOptions);
  204. foreach (var item in query)
  205. {
  206. objs.Add(item);
  207. }
  208. return objs;
  209. }
  210. public async Task<List<T>> FindByparams<T>(Dictionary<string, object> dict)
  211. {
  212. //await InitializeCollection<T>();
  213. Type t = typeof(T);
  214. Boolean open = true;
  215. List<Filter> filters = new List<Filter>();
  216. string PKname = "";
  217. PropertyInfo[] properties = t.GetProperties();
  218. List<PropertyInfo> attrProperties = new List<PropertyInfo>();
  219. foreach (PropertyInfo property in properties)
  220. {
  221. object[] attributes = property.GetCustomAttributes(true);
  222. foreach (object attribute in attributes) //2.通过映射,找到成员属性上关联的特性类实例,
  223. {
  224. if (attribute is PartitionAttribute)
  225. {
  226. PKname = property.Name;
  227. break;
  228. }
  229. }
  230. }
  231. foreach (string key in dict.Keys)
  232. {
  233. //if (t.Name.Equals(key)) {
  234. // open = false;
  235. //}
  236. if (PKname.Equals(key))
  237. {
  238. open = false;
  239. }
  240. filters.Add(new Filter { Key = key, Value = dict[key] != null ? dict[key].ToString() : throw new Exception("参数值不能为null") });
  241. }
  242. //List<T> objs = new List<T>();
  243. await InitializeCollection<T>();
  244. //查询条数 -1是全部
  245. FeedOptions queryOptions = new FeedOptions { MaxItemCount = -1, EnableCrossPartitionQuery = open };
  246. var query = CosmosClient.CreateDocumentQuery<T>(UriFactory.CreateDocumentCollectionUri(_Database, t.Name), queryOptions);
  247. List<T> list = DynamicLinq.GenerateFilter<T>(query, filters).ToList();
  248. return list;
  249. //return CosmosClient.CreateDocumentQuery<T>(UriFactory.CreateDocumentCollectionUri(_Database, t.Name),sql);
  250. }
  251. public async Task<string> DeleteAsync<T>(string id)
  252. {
  253. Type t = typeof(T);
  254. await InitializeCollection<T>();
  255. ResourceResponse<Document> doc =
  256. await CosmosClient.DeleteDocumentAsync(UriFactory.CreateDocumentUri(_Database, t.Name, id));
  257. //Console.WriteLine(doc.ActivityId);
  258. return id;
  259. throw new NotImplementedException();
  260. }
  261. }
  262. }