我遇到了令我困惑的问题。当我尝试将两个表联合在一起时,对第二个表的查询是生成一个返回第一个表的内部联接。使用union的重点是如果记录存在于任一个表中,则返回结果,但如果记录在第二个表中而不是第一个表中,则此内部联接会导致它失败。
我做了一些小规模的测试,看看我是不是疯了,而事实似乎并非如此。
我有两个表,OrderDetails和OrderDetailHistories。背景故事:在一段时间后,记录将从详细信息表中删除并放入历史记录表中。字段和一切都完全相同。实际上,这是OrderDetailHistories的实体:
public partial class OrderDetailsHistory : OrderDetail { }
所以,首先,我写了一个小测试查询,它很好地代表了我所看到的。
var test = this.context.OrderDetails
.Select(x => x.Descr)
.Union(this.context.OrderDetailsHistories
.Select(x => x.Descr))
.Where(x => x == "wat")
.ToList();
生成此查询:
SELECT
[Distinct1].[C1] AS [C1]
FROM ( SELECT DISTINCT
[UnionAll1].[Descr] AS [C1]
FROM (SELECT
[Extent1].[Descr] AS [Descr]
FROM [dbo].[OrderDetails] AS [Extent1]
WHERE N'wat' = [Extent1].[Descr]
UNION ALL
SELECT
[Extent3].[Descr] AS [Descr]
FROM [dbo].[OrderDetails_History] AS [Extent2]
INNER JOIN [dbo].[OrderDetails] AS [Extent3] ON ([Extent2].[Order_No] = [Extent3].[Order_No])
WHERE N'wat' = [Extent3].[Descr]) AS [UnionAll1]
) AS [Distinct1]
咦?为什么第二个select语句甚至引用了详细信息表?当我使用concat时会发生什么?一样。相交?相同的内部联接。好的,也许不是先结合,然后应用我的条件,我可以将条件应用于每个查询,然后将结果合并。
这个怎么样?
var query1 = this.context.OrderDetails.Where(x => x.Descr == "wat").Select(x => x.Descr);
var query2 = this.context.OrderDetailsHistories.Where(x => x.Descr == "wat").Select(x => x.Descr);
var result = query1.Concat(query2).ToList();
生成几乎完全相同的查询!有谁知道这里发生了什么?我的期望刚刚结束吗?
如果我在上面的query1和query2语句的末尾抛出一个.ToList(),它就像我期望的那样工作,但后来我失去了在sql中进行分页并最终拉下远的能力记录太多,我们每页只显示10个。
任何帮助都将不胜感激。
答案 0 :(得分:1)
我不知道您使用的是哪种EF方法,我想代码首先。但无论如何,你使用它错了或者你不知道它是如何工作的。当您从OrderDetailsHistory
继承OrderDetail
班级时,它会说OrderDetailsHistory
始终为OrderDetail
。
因此,如果您想选择所有订单,只需查询OrderDetail
,并且还会有所有OrderDetailsHistory
个实体:
this.context.OrderDetails
.Select(x => x.Descr)
.Where(x => x == "wat")
.ToList();
了解数据如何存储在数据库中也很重要。您正在使用每个类的表格 - 阅读一些关于它的文章(例如http://weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-2-table-per-type-tpt)以了解它是如何工作的,然后您也将理解为什么您的所有查询看起来“如此奇怪”......