如何跟踪 documentdb Linq 提供程序生成的查询?
How can I trace the query produced by the documentdb Linq provider?
如何在将 linq 语句发送到服务器之前查看文档数据库 sql 查询(在字符串中)?
_documentClient.CreateDocumentQuery<MyType>(
UriFactory.CreateDocumentCollectionUri(DatabaseName,
CollectionName)).Where(....).SelectMany(...)
我想将其用于跟踪目的。
您可以在 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"
您可以只使用 Fiddler 并在请求发送后查看 JSON。
在此处查看示例:
CosmosDB\DocumentDB Generated SQL Query
接受的答案有点奇怪:这意味着您必须记录您编写的每一段 Linq 代码。
(使用 AspNetCore DI)。
知道 Microsoft.Azure.Cosmos.CosmosClient
包含一个 HttpClient
,我们可以做的第一件事就是搜索是否可以传递我们自己的 HttpClient
.
我们可以。例如,通过 CosmosClientBuilder
并使用注入的 IHttpClientFactory
:
.WithHttpClientFactory(() => httpClientFactory.CreateClient("Client"))
如果您的日志过滤器配置正确,您将在控制台中看到请求/响应。
现在,我们可以在 ConfigureServices
中以这种方式将 DelegatingHandler
添加到我们的 HttpClient
中,或者在 .NET 6 中以这种方式添加 builder.Services
:
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;
}
}
好了。我尝试缩短代码,例如,我没有添加检查日志级别是否启用的条件,以避免做无用的工作。
如何在将 linq 语句发送到服务器之前查看文档数据库 sql 查询(在字符串中)?
_documentClient.CreateDocumentQuery<MyType>(
UriFactory.CreateDocumentCollectionUri(DatabaseName,
CollectionName)).Where(....).SelectMany(...)
我想将其用于跟踪目的。
您可以在 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"
您可以只使用 Fiddler 并在请求发送后查看 JSON。
在此处查看示例:
CosmosDB\DocumentDB Generated SQL Query
接受的答案有点奇怪:这意味着您必须记录您编写的每一段 Linq 代码。
(使用 AspNetCore DI)。
知道 Microsoft.Azure.Cosmos.CosmosClient
包含一个 HttpClient
,我们可以做的第一件事就是搜索是否可以传递我们自己的 HttpClient
.
我们可以。例如,通过 CosmosClientBuilder
并使用注入的 IHttpClientFactory
:
.WithHttpClientFactory(() => httpClientFactory.CreateClient("Client"))
如果您的日志过滤器配置正确,您将在控制台中看到请求/响应。
现在,我们可以在 ConfigureServices
中以这种方式将 DelegatingHandler
添加到我们的 HttpClient
中,或者在 .NET 6 中以这种方式添加 builder.Services
:
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;
}
}
好了。我尝试缩短代码,例如,我没有添加检查日志级别是否启用的条件,以避免做无用的工作。