linq中的外连接

时间:2012-05-27 10:49:49

标签: linq entity-framework c#-4.0 join

我在sqlServer中有3个表如下:

Cost_Types

Id   COST_NAME
-------------
1      A
2      B
3      C
4      D
5      E
6      F
7      Z

和请求表

Id   No
----------
1     100
2     200
3     300

和Cost_Request(= clearance_cost)

RequestId     CostId   Amount
-------------------------------
1               2       200
1               3       400

我想获得此结果

RequestId     CostId   Amount
    -------------------------------
    1               2       200
    1               3       400
    1               1        0
    1               4        0
    1               5        0
    1               6        0

我写这段代码

var context = new CLEARANCEEntities();
        var items = (from c in context.COST_TYPES
                     join t in context.CLEARANCE_COST
                         on c.COST_ID equals t.COST_ID into outer
                     from t in outer.DefaultIfEmpty()
                     where t. RequestId==1
                     select new
                          {
                            c.COST_ID,
                            c.COST_NAME, I = ((t == null) ? 0 : t.COST_AMOUNT)
                          }).ToList();

此代码只返回此

    RequestId     CostId   Amount
    -------------------------------
    1               2       200
    1               3       400

我希望如果更改查询如下:

var context = new CLEARANCEEntities();
            var items = (from c in context.COST_TYPES
                         join t in context.CLEARANCE_COST
                             on c.COST_ID equals t.COST_ID into outer
                         from t in outer.DefaultIfEmpty()
                         where t.RequestId==2               
                         select new
                                    {
                                        c.COST_ID,
                                        c.COST_NAME, I = ((t == null) ? 0 : t.COST_AMOUNT)
                                    }).ToList();

返回此数据

 RequestId     CostId   Amount
    -------------------------------
    2               1      0
    2               2      0
    2               3      0
    2               4      0
    2               5      0
    2               6      0

请帮帮我。谢谢所有

3 个答案:

答案 0 :(得分:4)

我知道LEFT JOIN'ing的GroupJoin-> SelectMany-> DefaultIfEmpty技术很受欢迎......但我认为SelectMany-> NavigationPropertyJoin-> DefaultIfEmpty技术更加清晰。

var query =
  from c in context.CostTypes
  from xr in c.CostRequests
    .Where(xrRecord => xrRecord.RequestId == 1)
    .DefaultIfEmpty()
  select new {
    CostType = c,
    Amount = xr == null ? 0 : xr.Amount
  }

答案 1 :(得分:2)

在对问题有不同理解后完全修改答案:

新答案

尝试将WHERE条件移动到JOIN子句。

你没有进行内部联接 - 所以联接的条件在这里是可以的,并且当你有匹配时不会消除你的空值。但是如果你把t.RequestId ==放在where子句中的任何内容你只是将它们过滤掉了。

老问题 - 无法解决的错误问题 看起来CostId和RequestId已经插入到Cost_Request表中,因此您正在进行左连接并且加入c.COST_ID等于t.COST_ID但是t.COST_ID实际上包含表中实际数据中的RequestId。这将完全解释您所看到的结果集。 要测试此理论,请将您的联接更改为

c.COST_ID equals t.REQUEST_ID 

看看你是否得到了你期望的结果。 虽然没有看到您的实体模型,但这很难,因为提供的查询与提供的表中的名称不匹配,我正在做一些猜测。

答案 2 :(得分:1)

对我而言,您似乎正在使用where t == 1语句过滤掉所有其他行。我不确定那个阶段你可以过滤它的t - 它似乎对应于clearence_cost.request_id。

您是否尝试过没有where子句的查询?

此外,您在select语句中的内容非常混乱:

 select new
         {
            c.COST_ID,
            c.COST_NAME, 
            I = ((t == null) ? 0 : t.COST_AMOUNT)
          }

查看'预期'结果集似乎c.Cost_id == requestId?,c.CostName == cost_id?什么是Cost_name?

老实说,如果你想要解决这个问题的答案,你必须花一些时间在你的帖子中先整理一下。你不能指望人们猜出为什么这些名字是不同的,并且神奇地知道你的意思。