gpt4 book ai didi

azure - Azure DocumentDB (CosmosDB) .Net SDK 中的位置

转载 作者:行者123 更新时间:2023-12-03 13:46:11 24 4
gpt4 key购买 nike

看过this question我不确定为什么我的 DocDb 实例的以下代码不起作用:

var userApps = _docs.CreateDocumentQuery(UriFactory.CreateDocumentCollectionUri(Constants.Databases.Applications.ID, Constants.Databases.Applications.Collections.USER_APPS),
new SqlQuerySpec(@"SELECT r.appId FROM ROOT r WHERE r.userId = @userId", (@"@userId", userId).ToSqlParameters()))
.ToList()
.Select(s => (string)s.appId);
var query = _docs.CreateDocumentQuery<Document>(UriFactory.CreateDocumentCollectionUri(Constants.Databases.Applications.ID, Constants.Databases.Applications.Collections.APP_DEFINITIONS),
new SqlQuerySpec(@"SELECT r.id, r.appName FROM ROOT r WHERE r.appId IN (@userApps)", (@"@userApps", userApps.ToArray()).ToSqlParameters()),
new FeedOptions { EnableCrossPartitionQuery = true })
.AsDocumentQuery();

当我执行此操作时,尽管我知道数据应该返回结果集,但每次它都返回空。

到目前为止的故障排除

.Select() 的变体

将我 string.Join 加入的字符串返回到以逗号分隔的列表中。

例如:

var userApps = string.Join(@",", _docs.CreateDocumentQuery(UriFactory.CreateDocumentCollectionUri(Constants.Databases.Applications.ID, Constants.Databases.Applications.Collections.USER_APPS),
new SqlQuerySpec(@"SELECT r.appId FROM ROOT r WHERE r.userId = @userId", (@"@userId", userId).ToSqlParameters()))
.ToList()
.Select(s => $@"'{s.appId}'");

不要封装IN参数

删除查询中参数规范周围的 (),认为 SqlParameter 规范可能正在执行数组规范?

例如:@“从ROOT r WHERE r.appId IN @userApps中选择r.id,r.appName”)

最终抛出“语法错误,‘@userApps’附近的语法不正确。”

通过 Azure 门户查询进行验证

运行此代码应运行的(预期)SQL。

我毫无问题地得到了预期的结果(即:我知道这些查询有一个书面的结果集)。

查询 1 的调试器输出

AppId从查询 1 返回。

不令人满意的解决方法

将查询 2 更改为参数化。相反,将查询 1 中以逗号分隔的 ID 列表注入(inject)其中:

var userApps = string.Join(@",", _docs.CreateDocumentQuery(UriFactory.CreateDocumentCollectionUri(Constants.Databases.Applications.ID, Constants.Databases.Applications.Collections.USER_APPS),
new SqlQuerySpec(@"SELECT r.appId FROM ROOT r WHERE r.userId = @userId", (@"@userId", userId).ToSqlParameter()))
.ToList()
.Select(s => $@"'{s.appId}'"));
var query = _docs.CreateDocumentQuery<Document>(UriFactory.CreateDocumentCollectionUri(Constants.Databases.Applications.ID, Constants.Databases.Applications.Collections.APP_DEFINITIONS),
new SqlQuerySpec($@"SELECT r.id, r.appName FROM ROOT r WHERE r.appId IN ({userApps})"),
new FeedOptions { EnableCrossPartitionQuery = true })
.AsDocumentQuery();

工作完美,但我不会接受它作为这个问题的答案,因为它违背了几十年来的 SQL 最佳实践,坦率地说,不应该成为一个解决方案.

<小时/>

这是我的 ToSqlParameters() 扩展方法,以防万一它是罪魁祸首(不过,这在我使用过它的其他地方都有效。也许数组需要一些特殊的东西?):

public static SqlParameterCollection ToSqlParameters(this (string, object) parmDef) => new SqlParameterCollection(new[] { new SqlParameter(parmDef.Item1, parmDef.Item2) });

谢谢!

最佳答案

如果您使用参数化 IN 列表,那么当参数展开时它将被视为单个值。

例如,对于此查询:

SELECT * FROM r WHERE r.item IN (@items) And @items is defined as "['val1', 'val2', 'val3']"将被解释为:

SELECT * FROM r WHERE r.item IN (['val1', 'val2', 'val3'])这基本上意味着您将 r.item 与一个包含三个元素的数组的值进行比较(即相当于 r.item = ['val1', 'val2', 'val3'])

要比较多个项目,您需要为每个值使用一个参数。像这样的:SELECT * FROM r WHERE r.item IN (@val1, @val2, @val3])

编写此查询的更方便的方法是使用 ARRAY_CONTAINS 并将项目数组作为单个参数传递。所以上面的查询会这样写:

SELECT * FROM r WHERE ARRAY_CONTAINS(@items, r.item)

关于azure - Azure DocumentDB (CosmosDB) .Net SDK 中的位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44636971/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com