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

Tuu*_*emi 11 .net c# azure azure-cosmosdb

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

var response = await client.ReadDocumentAsync( documentUri );
Run Code Online (Sandbox Code Playgroud)

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

Mat*_*nta 9

遗憾的是没有其他办法,无论是处理异常还是进行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
}
Run Code Online (Sandbox Code Playgroud)

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

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

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


Dav*_*gon 8

你专门查询一个给定的文件,并ReadDocumentAsync会抛出DocumentClientException时,它无法找到特定文件(在状态代码返回404).这在此处记录.通过捕获异常(并看到它是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())
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

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

  • 奇怪的是,我们不得不求助于例外.通过异常进行通信通常会变得昂贵,因为异常往往很重,而且通常是禁止的.在这种情况下,因为这通过TCP,服务器需要返回一个代码,在这种情况下,它是一个404.所以它有点像一个必要的邪恶.我喜欢使用查询来查看是否有任何结果.这不会导致例外.使用try catch,代码看起来也很奇怪. (6认同)
  • 无论如何,您可能都想处理异常,所以这似乎比预检检查是否存在更好,恕我直言。 (2认同)