具有指定ID的CosmosDB实体不存在

时间:2019-05-18 02:33:09

标签: c# asp.net-core azure-cosmosdb

我正在开发ASP.NET Core MVC API,以调用Azure Cosmos DB中的资源。当我尝试对任何特定ID执行GET时,我收到DocumentClientException:具有指定ID的实体在系统中不存在。我可以确认该实体确实存在于系统中,并且连接成功,因为我可以成功执行其他方法和请求。分区键是_id。

在Visual Studio中使用断点进行调试,我可以看到在API处接收到正确ID的位置,但是我无法确认它具体发送到Azure的位置

控制器方法:(ID字段是数字和文本的随机字符串)

        //controller is MoviesController decorated with [Route(api/[controller])]
    //sample GET is to localhost:port/api/Movies/5ca6gdwndkna99
        [HttpGet("{id}")]
        public async Task<MoviesModel> Get(string id)
        {
            MoviesModel movie = await _persistence.GetMovieAsync(id);
            return movie;
        }

数据处理方法:

public async Task<MoviesModel> GetMovieAsync(string Id)
        {

            string _id = Id;
            RequestOptions options = new RequestOptions();
            options.PartitionKey = new PartitionKey(_id);
            var documentUri = UriFactory.CreateDocumentUri(_databaseId, "movies", Id);
            Document result = await _client.ReadDocumentAsync(documentUri,options);

            return (MoviesModel)(dynamic)result;
        }

其他方法,例如获取所有电影的列表并返回表格,都可以正常工作,因此我们可以排除网络问题

public async Task<List<MoviesModel>> GetMoviesAsync() 
{
var documentCollectionUri = UriFactory.CreateDocumentCollectionUri(_databaseId, "movies");

            // build the query
            var feedOptions = new FeedOptions() { EnableCrossPartitionQuery = true };
            var query = _client.CreateDocumentQuery<MoviesModel>(documentCollectionUri, "SELECT * FROM movies", feedOptions);
            var queryAll = query.AsDocumentQuery();

            // combine the results
            var results = new List<MoviesModel>();
            while (queryAll.HasMoreResults)
            {
                results.AddRange(await queryAll.ExecuteNextAsync<MoviesModel>());
            }

            return results;
        }


        public async Task<List<GenresModel>> GetGenresAsync()
        {
            await EnsureSetupAsync();

            var documentCollectionUri = UriFactory.CreateDocumentCollectionUri(_databaseId, "genres");

            // build the query
            var feedOptions = new FeedOptions() { EnableCrossPartitionQuery = true };
            var query = _client.CreateDocumentQuery<GenresModel>(documentCollectionUri, "SELECT * FROM genres", feedOptions);
            var queryAll = query.AsDocumentQuery();

            // combine the results
            var results = new List<GenresModel>();
            while (queryAll.HasMoreResults)
            {
                results.AddRange(await queryAll.ExecuteNextAsync<GenresModel>());
            }

            return results;
        }

2 个答案:

答案 0 :(得分:0)

首先,我建议重新检查一下您的cosmosDb设计,原因如下:

问题:

  1. 如果您的_id是数字和文本的随机字符串,则效果不佳 将整个_id作为您的分区键,请bcz这将创建一个 每个条目的新分区。(尽管azure将对其进行分区 稍后)

  2. 仅凭分区键查询效率不高     查询我们应该同时具有分区键和行键。

解决方案

  1. 将_id的前一个或两个字母作为分区键。 (因此您的分区将是有限的。)

  2. 将_id用作行键。

  3. 如果您的_id =“ abwed123asdf”,则您的查询应该是..

    RequestOptions选项=新的RequestOptions();

    options.PartitionKey =新的PartitionKey(_id.Substring(0,1));

    options.RowKey = _id;

这样,您的查找将在分区和行键的帮助下精确指向所需的条目。 (节省很多RU)

请参考文档,以根据您的需求选择更好的分区键https://docs.microsoft.com/en-us/azure/cosmos-db/partitioning-overview

答案 1 :(得分:0)

通过完全重构到dotnet v3 SDK,我能够使它正常工作。我的解决方案代码在gitHub链接的注释中。