阅读可能不存在的Azure DocumentDB文档

时间:2016-02-18 13:12:28

标签: c# .net azure azure-cosmosdb

我可以从Azure DocumentDB查询单个文档,如下所示:

var response = await client.ReadDocumentAsync( documentUri );

如果文档不存在,则会抛出DocumentClientException。在我的程序中,我遇到的情况是文档可能存在,也可能不存在。是否有任何方法可以在不使用try-catch的情况下查询文档,而无需两次往返服务器,首先查询文档,然后检索文档是否存在?

3 个答案:

答案 0 :(得分:8)

可悲的是,没有其他方法,无论是处理异常还是进行2次调用,如果选择第二条路径,这是检查文档存在的一种性能驱动方式:

public bool ExistsDocument(string id)
{
    var client = new DocumentClient(DatabaseUri, DatabaseKey);
    var collectionUri = UriFactory.CreateDocumentCollectionUri("dbName", "collectioName");
    var query = client.CreateDocumentQuery<Microsoft.Azure.Documents.Document>(collectionUri, new FeedOptions() { MaxItemCount = 1 });
    return query.Where(x => x.Id == id).Select(x=>x.Id).AsEnumerable().Any(); //using Linq
}

客户端应该在所有数据库访问方法中共享,但我在那里创建了一个自动足够的示例。

new FeedOptions () {MaxItemCount = 1}将确保查询将针对1个结果进行优化(我们真的不需要更多)。

Select(x=>x.Id)将确保不会返回任何其他数据,如果您没有指定它并且文档存在,它将查询并返回其所有信息。

答案 1 :(得分:7)

您专门查询指定的文档,ReadDocumentAsync会在找不到特定文档时返回DocumentClientException(在状态代码中返回404)。记录在案here。通过捕捉异常(并且看到它是404),您将不需要两次往返。

要绕过处理此异常,您需要使用CreateDocumentQuery()进行查询而不是离散读取。然后,您只需获取一个可以枚举的结果集(即使该结果集为空)。例如:

var collLink = UriFactory.CreateDocumentCollectionUri(databaseId, collectionId);
var querySpec = new SqlQuerySpec { <querytext> };

var itr = client.CreateDocumentQuery(collLink, querySpec).AsDocumentQuery();
var response = await itr.ExecuteNextAsync<Document>();

foreach (var doc in response.AsEnumerable())
{
    // ...
}

通过这种方法,您将得不到任何回复。在您的特定情况下,如果您要添加WHERE子句以按其ID查询特定文档,则您将获得零结果或一个结果。

答案 2 :(得分:0)

使用CosmosDB SDK版本。 3有可能。您可以检查容器中是否存在某项,并使用Container.ReadItemStreamAsync<T>(string id, PartitionKey key)并检查response.StatusCode来获取它:

using var response = await container.ReadItemStreamAsync(id, new PartitionKey(key));

if (response.StatusCode == HttpStatusCode.NotFound)
{
    return null;
}

if (!response.IsSuccessStatusCode)
{
    throw new Exception(response.ErrorMessage);
}

using var streamReader = new StreamReader(response.Content);

var content = await streamReader.ReadToEndAsync();

var item = JsonConvert.DeserializeObject(content, stateType);

但是,这种方法有一个缺点。您需要手动反序列化该项目。