【问题标题】:LINQ OUTER JOIN Query - Null in Where clause not workingLINQ OUTER JOIN 查询 - Where 子句中的 Null 不起作用
【发布时间】:2017-01-16 17:11:25
【问题描述】:

在我的以下示例数据表中,客户 C1 订购了蔬菜,而 C2 订购了水果。我想显示尚未订购的潜在客户 C3 和 C4 的名称。所以,我使用Outer Join,但查询总是返回第一个客户 C1。看来,我的 where 子句有问题。

客户表

CustomerID  CustName
1           C1
2           C2
3           C3
4           C4

订单表

OrderID CustomerID  OrderType
1       1           V
2       2           F
3       1           V

LINQ Query 显示尚未订购的潜在客户:

    public class TestDbController : Controller
    {

       public async Task<IActionResult> TestAction(List<CustomersViewModel> list)
       {
          var Qry = from c in Customers
                     join ord in Orders on c.CustomerId equals ord.CustomerId into c_o
                     from t in c_o.DefaultIfEmpty()
                     where t == null
                     select new  CustomersViewModel() {CustName = c.Name};
          return View(qry.ToList());
        }
    }

更新

根据@IvanStoev 的说法,这似乎是一个 EF 核心错误。我应该指出我正在使用以下技术:ASP.NET CORE、EF Core、Visual Studio 2015 - UPDATE 3 和 SQL Server Express 2014。我在帖子中包含了 EF Core 的标签。

如果有人能找到解决方案或变通方法,请告诉我。

更新 2

SQL Server Profiler 捕获以下 SQL:

exec sp_executesql N'SELECT [c].[CustNumber], @__Empty_0
FROM [Customers] AS [c]
LEFT JOIN [Orders] AS [ord] ON [c].[CustomerID] = [ord].[CustomerID]
ORDER BY [c].[CustomerID]',N'@__Empty_0 nvarchar(4000)',@__Empty_0=N''

但我的观点是只显示一条记录。另外,当我在下面显示的视图中在@for (int t=0; t&lt;Model.Count; t++) 处放置断点时,它在Model.Count 处仅显示1:

@model List<MyProject.Models.MyViewModels.CustomersViewModel>

    <form asp-controller="TestDb" asp-action="TestAction" method="post">
    <table class="table">
      <thead>
         <tr>
             <th><label asp-for="@Model.First().CustName"></label></th>
         </tr>
       </thead>
       <tbody>
             @for (int t=0; t<Model.Count; t++)
                {
                  <tr>
                     <td><input type="hidden" asp-for="@Model[t].CustomerId"/ </td>
                     <td><input type="text" asp-for="@Model[t].CustName"/></td>
                  </tr>
                }
       </tbody>
      </table>
      <button type="submit">Save</button>
  </form>

【问题讨论】:

  • 应该是 where t == null 以在 c 中查找没有 t 的行(即左连接的空右侧)。这与将检查特定列/值是否为空的普通 SQL 不同。请参阅 stackoverflow.com/a/3413732/2864740 作为简单参考。
  • @user2864740 是的,这就是我的意思。我纠正了你提到的错字。但仍然是同样的问题。
  • 我调试的下一步是检查生成的 SQL。 (这对于 SQL Server 和附加的 SQL Profiler 会话来说非常简单/非侵入性。)
  • 这里肯定发生了其他事情。该代码适用于 dotnetFiddle 中的 POCO
  • @user2864740 在执行过程中可能只需将鼠标悬停在Qry 变量上,也可以查看 SQL。

标签: c# linq visual-studio-2015 entity-framework-core


【解决方案1】:

这实际上是您的查询并且有效(反对说 Northwind):

var Qry = from c in Customers
              join ord in Orders on c.CustomerID equals ord.CustomerID into c_o
              from t in c_o.DefaultIfEmpty()
              where t == null
              select c;

但更简单的说法是:

var Qry = from c in Customers
          where !c.Orders.Any()
          select c;

【讨论】:

  • OP 报告查询未按预期工作 - 唯一明显的变化似乎是 select 子句:}
  • 我说它按要求工作,什么是“不希望”?
  • OP 报告它没有返回丢失的行,而是返回成功连接的单行(“..但是查询总是返回第一个客户 C1”)。虽然我对这些结果持怀疑态度,并且我怀疑还有其他问题,但这是报告的行为。
  • 我只是重申提出的问题和问题中的陈述。
  • 我说的是“[在这个答案中]唯一明显的变化看起来是 select 子句”:}
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-24
  • 2020-03-09
  • 1970-01-01
  • 2011-01-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多