【发布时间】:2017-06-19 17:53:22
【问题描述】:
看到 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 规范正在执行数组规范?
例如:@"SELECT r.id, r.appName FROM ROOT r WHERE r.appId IN @userApps")
最终抛出“语法错误,'@userApps' 附近的语法不正确。”
通过 Azure 门户查询验证
运行此代码应该运行的(预期的)SQL。
我毫无问题地返回了我的预期结果(即:我知道这些查询有一个按原样编写的结果集)。
查询 1 的调试器输出
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();
完美运行,但我不会接受它作为这个问题的答案,因为它违背了数十年的 SQL 最佳实践,坦率地说,不应该成为一个解决方案.
这是我的 ToSqlParameters() 扩展方法,以防万一它是罪魁祸首(不过,这在我使用过的其他任何地方都有效。也许数组需要一些特殊的东西?):
public static SqlParameterCollection ToSqlParameters(this (string, object) parmDef) => new SqlParameterCollection(new[] { new SqlParameter(parmDef.Item1, parmDef.Item2) });
谢谢!
【问题讨论】:
标签: azure azure-cosmosdb