Cosmos DB-CreateCollectionIfNotExistsAsync通用方法

时间:2020-05-19 07:24:03

标签: c# azure azure-cosmosdb azure-cosmosdb-sqlapi

我正在使用cosmos DB,并且已经在以下通用存储库中创建了CRUD操作。

public class CosmosDBRepository : ICosmosDBRepository
    {
        private readonly DocumentClient _client;

        private readonly string DatabaseId = "FleetHub";

        public CosmosDBRepository()
        {
            var endpoint = CloudConfigurationManager.GetSetting("CosmoDbEndpoint");
            var authkey = CloudConfigurationManager.GetSetting("CosmoDbAuthKey");
            try
            {
                if (endpoint == null || authkey == null)
                {
                    throw new ArgumentNullException("CosmoDbEndpoint or CosmoDbAuthKey could not be found in the config file, check your settings.");
                }

                if (_client == null)
                {
                    _client = new DocumentClient(new Uri(endpoint), authkey, connectionPolicy: new ConnectionPolicy { EnableEndpointDiscovery = false });
                }

                CreateDatabaseIfNotExistsAsync().Wait();
                CreateCollectionIfNotExistsAsync().Wait();
            }
            catch (Exception e)
            {
                throw new Exception($"Initialise failed CosmoDbEndpoint {endpoint} or CosmoDbAuthKey {authkey} could not be found in the config file, check your settings. {e.Message}");
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <param name="partitionkey"></param>
        /// <returns></returns>
        public async Task<T> GetItemAsync<T>(string id, string partitionkey) where T : class
        {
            try
            {
                string CollectionId = GetAttributeCosmoDbCollection<T>(typeof(T));

                Document document = await _client.ReadDocumentAsync(UriFactory.CreateDocumentUri(DatabaseId, CollectionId, id), new RequestOptions { PartitionKey = new PartitionKey(partitionkey) });
                return (T)(dynamic)document;
            }
            catch (DocumentClientException e)
            {
                if (e.StatusCode == System.Net.HttpStatusCode.NotFound)
                {
                    return null;
                }
                else
                {
                    throw;
                }
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public async Task<Document> CreateItemAsync<T>(T item) where T : class
        {
            string CollectionId = GetAttributeCosmoDbCollection<T>(typeof(T));
            return await _client.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri(DatabaseId, CollectionId), item);
        }
        public async Task<IEnumerable<T>> GetItemsAsync<T>(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderByDesc, int takeCount = -1)
            where T : class
        {
            string CollectionId = GetAttributeCosmoDbCollection<T>(typeof(T));

            var criteria = _client.CreateDocumentQuery<T>(
                        UriFactory.CreateDocumentCollectionUri(DatabaseId, CollectionId), new FeedOptions { EnableCrossPartitionQuery = true })
                    .Where(predicate)
                    .OrderByDescending(orderByDesc)
                    .AsDocumentQuery();

            IDocumentQuery<T> query = criteria;

            List<T> results = new List<T>();
            while (query.HasMoreResults)
            {
                if (takeCount > -1 && results.Count >= takeCount)
                {
                    break;
                }
                results.AddRange(await query.ExecuteNextAsync<T>());
            }

            return results;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <returns></returns>
        public async Task<Document> UpdateItemAsync<T>(string id, T item) where T : class
        {
            string CollectionId = GetAttributeCosmoDbCollection<T>(typeof(T));

            return await _client.ReplaceDocumentAsync(UriFactory.CreateDocumentUri(DatabaseId, CollectionId, id), item);
        }
        #region private methods
        private async Task CreateDatabaseIfNotExistsAsync()
        {
            try
            {
                await _client.ReadDatabaseAsync(UriFactory.CreateDatabaseUri(DatabaseId));
            }
            catch (DocumentClientException e)
            {
                if (e.StatusCode == System.Net.HttpStatusCode.NotFound)
                {
                    await _client.CreateDatabaseAsync(new Database { Id = DatabaseId });
                }
                else
                {
                    throw;
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        private string GetPartitionKeyAttributeCosmoDbCollection(Type t)
        {
            // Get instance of the attribute.
            CosmoDBCollection attribute =
                (CosmoDBCollection)Attribute.GetCustomAttribute(t, typeof(CosmoDBCollection));

            if (attribute == null)
            {
                throw new Exception("The attribute CosmoDbCollection was not found.");
            }

            return attribute.PartitionKey;
        }

        private string GetAttributeCosmoDbCollection<T>(Type t) where T : class
        {
            // Get instance of the attribute.
            CosmoDBCollection attribute =
                (CosmoDBCollection)Attribute.GetCustomAttribute(t, typeof(CosmoDBCollection));

            if (attribute == null)
            {
                throw new Exception("The attribute CosmoDbCollection was not found.");
            }

            return attribute.Name;
        }
        #endregion
    }

这是CosmoDBCollection类:

public class CosmoDBCollection : Attribute
    {
        public string Name { get; set; }

        public string PartitionKey { get; set; }
    }

我在构造函数中调用CreateCollectionIfNotExistsAsync().Wait();,此方法需要collectionId。如何将CollectionId传递给此方法?因为这是通用存储库。

我需要创建通用CreateCollectionIfNotExistsAsync()方法吗?

1 个答案:

答案 0 :(得分:0)

如果您的集合名称基于<T>,为什么不简单将CosmosDBRepository<T>作为实际类。这样,您还可以在构造函数上获取值。

理想情况下,它也将是readonly私有属性,您只需(在构造函数上)计算一次,并在所有操作上重用,以避免以后支付构造它的成本(因为它不变)。