bc3*_*ech 1 azure azure-cosmosdb
看到这个问题后,我不确定为什么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();
Run Code Online (Sandbox Code Playgroud)
当我执行此操作时,尽管我知道数据应该返回我一个结果集,但每次它都返回为空。
.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}'");
Run Code Online (Sandbox Code Playgroud)
在查询中删除参数规范周围的()可能是SqlParameter规范正在执行数组规范?
例如:@"SELECT r.id, r.appName FROM ROOT r WHERE r.appId IN @userApps")
最终抛出“语法错误,'@ userApps'附近的语法不正确”。
使(预期的)SQL运行该代码。
我得到的预期结果没有问题(即:我知道这些查询的结果集是书面的)。
AppIds 是未来从查询1回。
将查询2更改为未参数化。而是将查询1中以逗号分隔的ID列表注入其中:
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();
Run Code Online (Sandbox Code Playgroud)
可以完美地工作,但是我不会接受它作为此问题的答案,因为它与几十年来价值不菲的SQL最佳实践相抵触,坦率地说,不应该将其作为解决方案。
ToSqlParameters()如果是罪魁祸首,这是我的扩展方法(尽管这在我使用过的其他地方都可以使用。也许数组需要一些特殊的东西吗?):
public static SqlParameterCollection ToSqlParameters(this (string, object) parmDef) => new SqlParameterCollection(new[] { new SqlParameter(parmDef.Item1, parmDef.Item2) });
Run Code Online (Sandbox Code Playgroud)
谢谢!
如果使用参数化的IN列表,则在扩展参数时它将被视为单个值。
例如,对于该查询:SELECT * FROM r WHERE r.item IN(@items)而@items定义为“ [['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)
| 归档时间: |
|
| 查看次数: |
817 次 |
| 最近记录: |