我正在尝试减少数据库查询的数量,并且这样做我试图一次性检索一系列分层实体(以前是递归获取的)。
我有一个Labels
属性,其中包含一组字符串:
public string[] Labels { get; set; } // new string[] {"{{a}}", "{{b}}", "{{c}}", "{{d}}", "{{e}}"};
我正在使用构建第一个查询:
var IDeferredTopLabels=
db.labels
.Where(l =>
l.site_id == this.site_id &&
this.Labels.Contains(l.name_for_code)
)
.Select(l => new LabelWithParentId { Label = l, ParentId = null });
以上,如果在调试时检查,将生成以下TSQL
SELECT [t0].[id], [t0].[name_for_code], [t0].[site_id], [t0].[priority_level]
FROM [dbo].[labels] AS [t0]
WHERE ([t0].[site_id] = 15) AND ([t0].[name_for_code] IN ('{{a}}', '{{b}}', '{{c}}', '{{d}}', '{{e}}'))
到目前为止一直很好,在IDeferredToplabels
声明之后,我正在使用Union
扩展第一个查询,指定应如何获取子Label
个实体:
var IDeferredWithChildLabels = IDeferredTopLabels
.Union(
db.label__labels
.Where(ll =>
db.labels
.Where(l =>
l.site_id == this.site_id &&
this.Labels.Contains(l.name_for_code)
)
.Select(l => l.id)
.Contains(ll.parent_label_id)
)
.Select(ll => new LabelWithParentId { Label = ll.label1, ParentId = ll.parent_label_id})
);
现在,如果我检查TSQL生成是:
SELECT [t4].[id], [t4].[name_for_code], [t4].[site_id], [t4].[priority_level], [t4].[value] AS [ParentId]
FROM (
SELECT [t0].[id], [t0].[name_for_code], [t0].[site_id], [t0].[priority_level], NULL AS [value]
FROM [dbo].[labels] AS [t0]
WHERE ([t0].[site_id] = 15) AND ([t0].[name_for_code] IN ('{{a}}', '{{b}}', '{{c}}', '{{d}}', '{{e}}'))
UNION
SELECT [t2].[id], [t2].[name_for_code], [t2].[site_id], [t2].[priority_level], [t1].[parent_label_id] AS [value]
FROM [dbo].[label__label] AS [t1]
INNER JOIN [dbo].[labels] AS [t2] ON [t2].[id] = [t1].[label_id]
WHERE EXISTS(
SELECT NULL AS [EMPTY]
FROM [dbo].[labels] AS [t3]
WHERE ([t3].[id] = [t1].[parent_label_id]) AND ([t3].[site_id] = 15) AND ([t3].[name_for_code] IN ('{{a}}', '{{b}}', '{{c}}', '{{a}}'0, '{{a}}'1))
)
) AS [t4]
如果你在第二个TSQL查询的末尾看到了IN ('{{a}}', '{{b}}', '{{c}}', '{{a}}'0, '{{a}}'1))
部分,那么字符串集合在第二个最后一个元素旁边有一个不可预见的0和1,最后一个元素加上它不再是初始集合字符串(即“{{a}}”,“{{b}}”,“{{c}}”,“{{d}}”,“{{e}}”),而是'{{a}}', '{{b}}', '{{c}}', '{{a}}', '{{a}}'
我做错了什么!?
我很无能为力,感谢你的帮助,谢谢你。
编辑:
我只是尝试使用int[]
并比较id
而不是name_for_code
,我仍然将1和0附加到数组的最后2个元素中因为数组元素是错误的:
SELECT [t4].[id], [t4].[name_for_code], [t4].[site_id], [t4].[priority_level], [t4].[value] AS [ParentId]
FROM (
SELECT [t0].[id], [t0].[name_for_code], [t0].[site_id], [t0].[priority_level], NULL AS [value]
FROM [dbo].[labels] AS [t0]
WHERE ([t0].[site_id] = 15) AND ([t0].[id] IN (1, 2, 3, 4, 5))
UNION
SELECT [t2].[id], [t2].[name_for_code], [t2].[site_id], [t2].[priority_level], [t1].[parent_label_id] AS [value]
FROM [dbo].[label__label] AS [t1]
INNER JOIN [dbo].[labels] AS [t2] ON [t2].[id] = [t1].[label_id]
WHERE EXISTS(
SELECT NULL AS [EMPTY]
FROM [dbo].[labels] AS [t3]
WHERE ([t3].[id] = [t1].[parent_label_id]) AND ([t3].[site_id] = 15) AND ([t3].[id] IN (1, 2, 3, 10, 11))
)
) AS [t4]
答案 0 :(得分:2)
好的我发现了问题,实际上它在运行代码时没有发生但只是在调试模式下,特别是它似乎是Scott Gu的LINQ to SQL Debug Visualizer
中的错误这就是为什么我抓到的TSQL没有参数化,@ David B你提出了一个非常好的观点!
我将在Scott Gu的页面上发表评论,指出这个问题。
全部谢谢!
答案 1 :(得分:0)
尝试复制Labels
并在查询的第二部分(联盟)中使用它。 EG:
string[] LabelsCopy = new string[5];
Labels.CopyTo(LabelsCopy, 0);
然后在查询后设置一个断点并检查每个数组的内容(或用Console.WriteLine(String.Join(',',Labels))
打印出两个数组的内容。)
.Contains()
极不可能改变Labels
的内容,但如果是,那么你就会有证据。