看过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}'");
在查询思想中删除参数规范周围的()可能是SqlParameter规范正在进行数组规范吗?
例如:@"SELECT r.id, r.appName FROM ROOT r WHERE r.appId IN @userApps"
)
结束投掷&#34;语法错误,&#39; @ userApps&#39;附近的语法不正确。&#34;
执行此代码应运行的(预期)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();
完美的工作,但我不会接受它作为这个问题的答案,因为它违背了几十年的SQL最佳实践,坦率地说,不应该成为一个解决方案。
这是我的ToSqlParameters()
扩展方法,以防它成为罪魁祸首(这可以在我使用它的其他地方工作。但是数组可能需要特殊的东西吗?):
public static SqlParameterCollection ToSqlParameters(this (string, object) parmDef) => new SqlParameterCollection(new[] { new SqlParameter(parmDef.Item1, parmDef.Item2) });
谢谢!
答案 0 :(得分:4)
如果您使用参数化的IN列表,那么在扩展参数时它将被视为单个值。
例如,对于此查询: SELECT * FROM r WHERE r.item IN(@items) @items被定义为&#34; [&#39; val1&#39;,&#39; val2&#39;,&#39; val3&#39;]&#34;那么查询将被解释为: SELECT * FROM r WHERE r.item IN([&#39; val1&#39;,&#39; val2&#39;,&#39; val3&#39;]) 这基本上意味着您将r.item与单个值进行比较,该值是三个元素的数组(即相当于r.item = [&#39; val1&#39;,&#39; val2&#39; ,&#39; val3&#39;])。
要与多个项目进行比较,您需要为每个值使用一个参数。像这样的东西: SELECT * FROM r WHERE r.item IN(@ val1,@ val2,@ val3])
编写此查询的一种更方便的方法是使用ARRAY_CONTAINS,并将项数组作为单个参数传递。所以上面的查询将这样写: SELECT * FROM r WHERE ARRAY_CONTAINS(@items,r.item)