【问题标题】:How can I trace the query produced by the documentdb Linq provider?如何跟踪由 documentdb Linq 提供程序生成的查询?
【发布时间】:2016-12-07 17:29:13
【问题描述】:

在将 linq 语句生成的文档 DB sql 查询(以字符串形式)发送到服务器之前,如何查看它?

_documentClient.CreateDocumentQuery<MyType>(
                        UriFactory.CreateDocumentCollectionUri(DatabaseName,
                            CollectionName)).Where(....).SelectMany(...)

我想用这个来追踪。

【问题讨论】:

标签: c# linq azure-cosmosdb


【解决方案1】:

您可以在 DocumentDB 查询上调用 ToString() 以获取通过网络发送的 LINQ 表达式的 SQL 翻译。

string sql = client.CreateDocumentQuery<MyType>(collectionUri).Where(t => t.Name = "x").ToString();
// sql is somthing like SELECT * FROM c WHERE c["Name"] = "x"

【讨论】:

  • 如果你用Count()这个不行我已经找到了。
【解决方案2】:

您可以只使用 Fiddler 并在发送请求后查看其 JSON。

在此处查看示例:

CosmosDB\DocumentDB Generated SQL Query

【讨论】:

    【解决方案3】:

    接受的答案有点奇怪:这意味着您必须记录您制作的每一段 Linq 代码。

    (使用 AspNetCore DI)。 知道Microsoft.Azure.Cosmos.CosmosClient 包含HttpClient,我们可以做的第一件事就是搜索是否可以传递我们自己的HttpClient

    我们可以。例如,通过CosmosClientBuilder 并使用注入的IHttpClientFactory

    .WithHttpClientFactory(() => httpClientFactory.CreateClient("Client"))
    

    如果您的日志过滤器配置良好,您将在控制台中看到请求/响应。

    现在,我们可以在 ConfigureServices 或 .NET 6 中的 builder.Services 中将 DelegatingHandler 添加到 HttpClient 中:

    services.AddTransient<NoSqlLoggingDelegatingHandler>();
    services.AddHttpClient("Client")
        .AddHttpMessageHandler<NoSqlLoggingDelegatingHandler>();
    

    或者查看CosmosClient 是否可以添加我们自己的选项,当然可以(例如通过CosmosClientBuilder)。

    .AddCustomHandlers(
        new NoSqlLoggingDelegatingHandler(loggerFactory.CreateLogger<NoSqlLoggingDelegatingHandler>()))
    

    这样,我们就可以拦截发送的请求和响应了:

    public override async Task<ResponseMessage> SendAsync(RequestMessage request, CancellationToken cancellationToken)
    {
        _logger.LogInformation("Requesting {uri}.\n{query}",
                request.RequestUri, await GetQueryAsync(request.Content));
    
        ResponseMessage response = await base.SendAsync(request, cancellationToken);
    
        _logger.LogInformation("Requested {uri} - {status}",
        response.RequestMessage.RequestUri, response.StatusCode);
    
        return response;
    }
    

    GetQueryAsync 使用System.Text.Json 读取请求的主体流:

    private static async ValueTask<string?> GetQueryAsync(Stream content)
    {
        string? stringContents;
    
        // Create a StreamReader with leaveOpen = true so it doesn't close the Stream when disposed
        using (StreamReader sr = new StreamReader(content, Encoding.UTF8, true, 1024, true))
        {
            stringContents = await sr.ReadToEndAsync();
        }
    
        content.Position = 0;
    
        if (string.IsNullOrEmpty(stringContents))
        {
            return null;
        }
    
        try
        {
            using JsonDocument parsedJObject = JsonDocument.Parse(stringContents);
    
            return parsedJObject.RootElement.GetProperty("query").GetString();
        }
        catch (KeyNotFoundException)
        {
            return stringContents;
        }
        // Not a JSON.
        catch (JsonException)
        {
            return stringContents;
        }
    }
    

    你有它。我尝试过缩短代码,例如我没有添加条件来检查日志级别是否启用,以避免做无用的工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-30
      • 1970-01-01
      • 2023-03-15
      • 2012-08-29
      • 1970-01-01
      • 2017-09-24
      • 2016-08-30
      相关资源
      最近更新 更多