EF Core - 导致 CS1941 的多个连接条件
Posted
技术标签:
【中文标题】EF Core - 导致 CS1941 的多个连接条件【英文标题】:EF Core - multiple join conditions causing CS1941 【发布时间】:2021-12-21 17:29:18 【问题描述】:上下文
Itzik Ben-Gan 的T-SQL Fundamentals Third Edition一书在第 3 章中包含以下查询:
SELECT C.custid, C.companyname, O.orderid, O.orderdate
FROM Sales.Customers AS C
LEFT OUTER JOIN Sales.Orders AS O
ON O.custid = C.custid
AND O.orderdate = '20160212';
注意join子句有两个条件:
O.custid = C.custid
AND
O.orderdate = '20160212'
其他帖子中展示的技术
以下帖子(以及其他帖子)演示了如何通过JOIN
使用多个条件
LINQ to Entity : Multiple join conditions
LINQ Join with Multiple Conditions in On Clause
问题
根据上面分享的帖子,这是我想出的 EF Core 版本的查询:
var result =
from customer in db.Customers
join order in db.Orders
on
new
Key1 = customer.Custid,
Key2 = true
equals
new
Key1 = order.Custid,
Key2 = order.Orderdate == new DateTime(2016, 2, 12)
into Abc
from abc in Abc.DefaultIfEmpty()
select new
customer.Custid,
customer.Companyname,
Orderid = abc == null ? -1 : abc.Orderid,
Orderdate = abc == null ? new DateTime() : abc.Orderdate
;
但是,使用该代码时,join
上会出现一条红色波浪线,并显示以下消息:
CS1941:join 子句中的表达式之一的类型不正确。调用“GroupJoin”时类型推断失败。
docs.microsoft.com 上的编译器错误链接:
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/cs1941?f1url=%3FappId%3Droslyn%26k%3Dk(CS1941)
问题
我根据其他帖子中显示的示例对我的版本进行了建模。所以不确定我的例子中是什么导致了这个问题。
为给定的 SQL 调用设置 LINQ 查询的好方法是什么?
谢谢!
注意事项
如果您真的想自己运行查询,上述查询位于此处提供的项目中:
https://github.com/dharmatech/TSqlEf/blob/master/Chapter3e7/Program.cs
有关如何设置数据库,请参阅项目自述文件:
https://github.com/dharmatech/TSqlEf
克莱的建议
这是一种基于 Cly 的回答的方法,它使用 where
子句:
var result =
from customer in db.Customers
join order in db.Orders
on customer.Custid equals order.Custid
into Abc
from abc in Abc.DefaultIfEmpty()
where abc.Orderdate == new DateTime(2016, 2, 12)
select new
customer.Custid,
customer.Companyname,
Orderid = abc == null ? -1 : abc.Orderid,
Orderdate = abc == null ? new DateTime() : abc.Orderdate
;
如果我使用以下输出结果:
foreach (var item in result)
Console.WriteLine("0 1 2", item.Custid, item.Companyname, item.Orderid, item.Orderdate);
Console.WriteLine();
Console.WriteLine("0 rows", result.Count());
我得到以下信息:
48 Customer DVFMB 10883
45 Customer QXPPT 10884
76 Customer SFOGW 10885
3 rows
如果我在 SSMS 中运行原始 SQL 代码,我会得到 91 行。
书中的练习描述还指出,预计需要 91 行。这是练习文本和预期输出:
这里是解决方案文本,它涉及连接背后的微妙之处以及为什么where
在这种情况下不适用:
【问题讨论】:
我会尝试从加入中删除Key2
部分并将order.Orderdate == new DateTime(2016, 2, 12)
添加为where
。它根本不是连接表达式,而是连接实体一侧的过滤器。
@cly,感谢您的建议!你会说应该在哪里插入where
子句?我试图将它放在各个地方的查询中,它们都会导致错误。
试试from abc in Abc.Where(abc => abc.Orderdate == new DateTime(2016, 2, 12)).DefaultIfEmpty()
@Charlieface,Omgosh ......这似乎完美无缺!我添加了一个答案来说明您建议的方法:***.com/a/69892036/268581 非常有趣...谢谢!
@Charlieface,如果您决定根据您的建议添加自己的答案,我会投票赞成并删除我的。 :-)
【参考方案1】:
将Key2
not-so-join-but-a-side-filter 部分取出到where
看起来像这样:
var result =
from customer in db.Customers
join order in db.Orders
on customer.Custid equals order.Custid into Abc
from abc in Abc.DefaultIfEmpty()
where abc.Orderdate == new DateTime(2016, 2, 12)
select new
customer.Custid,
customer.Companyname,
Orderid = abc == null ? -1 : abc.Orderid,
Orderdate = abc == null ? new DateTime() : abc.Orderdate
;
【讨论】:
感谢克莱的澄清!所以,我从这个版本(3 行)得到的输出与本书所期望的(91 行)不同。我已经用一个部分更新了这个问题,该部分展示了你的方法,并包含了书中的注释,阐明了为什么where
会导致不同的结果。
新的细节显示了不同的要求。 “解决方案查询”中有一个您尚未使用的修饰符 :) 在我的版本中找到它的位置并使用适当的语法编写它。通过反复试验学习是一件非常好的事情! :)
嗯...有趣的提示!当您说查询中有一个修饰符不在您的版本中时,您指的是AND
吗?
Charlieface 的建议似乎奏效了。我已经在此基础上添加了答案。那里的方法是否与您的想法相似?【参考方案2】:
只需使用过滤的包括:https://docs.microsoft.com/en-us/ef/core/querying/related-data/eager#filtered-include
【讨论】:
【参考方案3】:查理脸的建议
这是一种基于 Charlieface 在上述评论中的建议的方法。它确实似乎有效!
var result =
from customer in db.Customers
join order in db.Orders
on customer.Custid equals order.Custid
into Abc
from abc in Abc.Where(abc => abc.Orderdate == new DateTime(2016, 2, 12)).DefaultIfEmpty()
select new
customer.Custid,
customer.Companyname,
Orderid = abc == null ? -1 : abc.Orderid,
Orderdate = abc == null ? new DateTime() : abc.Orderdate
;
使用以下输出结果:
foreach (var item in result)
Console.WriteLine("0,3 1 2,6 3,10",
item.Custid,
item.Companyname,
item.Orderid == -1 ? "NULL" : item.Orderid,
item.Orderid == -1 ? "NULL" : item.Orderdate.ToString("yyyy-MM-dd"));
显示以下内容:
72 Customer AHPOP NULL NULL
58 Customer AHXHT NULL NULL
25 Customer AZJED NULL NULL
18 Customer BSVAR NULL NULL
91 Customer CCFIZ NULL NULL
68 Customer CCKOT NULL NULL
49 Customer CQRAA NULL NULL
24 Customer CYZTN NULL NULL
22 Customer DTDMN NULL NULL
48 Customer DVFMB 10883 2016-02-12
10 Customer EEALV NULL NULL
40 Customer EFFTC NULL NULL
85 Customer ENQZT NULL NULL
82 Customer EYHKM NULL NULL
79 Customer FAPSM NULL NULL
17 Customer FEVNN NULL NULL
37 Customer FRXZL NULL NULL
33 Customer FVXPQ NULL NULL
53 Customer GCJSG NULL NULL
39 Customer GLLAG NULL NULL
16 Customer GYBBY NULL NULL
4 Customer HFBZG NULL NULL
5 Customer HGVLZ NULL NULL
42 Customer IAIJK NULL NULL
34 Customer IBVRG NULL NULL
63 Customer IRRVL NULL NULL
73 Customer JMIKW NULL NULL
15 Customer JUWXK NULL NULL
50 Customer JYPSC NULL NULL
3 Customer KBUDE NULL NULL
21 Customer KIDPX NULL NULL
30 Customer KSLQF NULL NULL
55 Customer KZQZT NULL NULL
71 Customer LCOUJ NULL NULL
77 Customer LCYBZ NULL NULL
66 Customer LHANT NULL NULL
38 Customer LJUCA NULL NULL
59 Customer LOLJO NULL NULL
36 Customer LVJSO NULL NULL
64 Customer LWGMD NULL NULL
29 Customer MDLWA NULL NULL
2 Customer MLTDN NULL NULL
78 Customer NLTYP NULL NULL
84 Customer NRCSK NULL NULL
1 Customer NRZBB NULL NULL
65 Customer NYUHS NULL NULL
44 Customer OXFRU NULL NULL
12 Customer PSNMQ NULL NULL
47 Customer PSQUZ NULL NULL
51 Customer PVDZC NULL NULL
52 Customer PZNLA NULL NULL
56 Customer QNIVZ NULL NULL
8 Customer QUHWH NULL NULL
67 Customer QVEPD NULL NULL
45 Customer QXPPT 10884 2016-02-12
7 Customer QXVLA NULL NULL
60 Customer QZURI NULL NULL
19 Customer RFNQC NULL NULL
9 Customer RTXGC NULL NULL
76 Customer SFOGW 10885 2016-02-12
69 Customer SIUIH NULL NULL
86 Customer SNXOJ NULL NULL
88 Customer SRQVM NULL NULL
54 Customer TDKEG NULL NULL
20 Customer THHDP NULL NULL
70 Customer TMXGN NULL NULL
11 Customer UBHAU NULL NULL
43 Customer UISOJ NULL NULL
35 Customer UMTLM NULL NULL
26 Customer USDBG NULL NULL
13 Customer VMLOG NULL NULL
80 Customer VONTK NULL NULL
62 Customer WFIZJ NULL NULL
27 Customer WMFEA NULL NULL
14 Customer WNMAF NULL NULL
61 Customer WULWD NULL NULL
57 Customer WVAXS NULL NULL
23 Customer WVFAF NULL NULL
90 Customer XBBVR NULL NULL
6 Customer XHXJV NULL NULL
41 Customer XIIWM NULL NULL
75 Customer XOJYP NULL NULL
46 Customer XPNIK NULL NULL
28 Customer XYUFB NULL NULL
89 Customer YBQTI NULL NULL
31 Customer YJCBX NULL NULL
81 Customer YQQWW NULL NULL
74 Customer YSHXL NULL NULL
32 Customer YSIQX NULL NULL
87 Customer ZHYOS NULL NULL
83 Customer ZRNDE NULL NULL
91 rows
【讨论】:
以上是关于EF Core - 导致 CS1941 的多个连接条件的主要内容,如果未能解决你的问题,请参考以下文章