代码之家  ›  专栏  ›  技术社区  ›  IAbstract

正确的Join/GroupJoin实现

  •  3
  • IAbstract  · 技术社区  · 15 年前

    TableA TableB 数据映射如下:

    class MyDataContext : DataContext
    {
        public Table<tblA> TableA;
        public Table<tblB> TableB;
    }
    

    作为我的主表并希望加入一个字段, CustomerID 表B 检索 [TableB].[LastName] .

    here ,我模仿@tvanfosson的建议:

    // appropriately rewritten for my needs - so I thought...
    private static IQueryable GetRecordsByView1(IQueryable<tblA> source)
    {
        var records = source.GroupJoin(myContext.TableB,
                      info => info.CustomerID,
                      owner => owner.CustomerID,
                      (info, owner) => new
                      {
                          info.CustomerID,
                          Owner = owner.Select(o => o.LastName).DefaultIfEmpty(),
                          Store = info.Store,
                      })
                      .Select(record => new
                      {
                          record.CustomerID,
                          record.Owner,
                          record.Store,
                      });
    
        return records;
    }
    

    source 是动态的,因此一个方法生成动态查询:

    public static void QueryStores()
    {
        IQueryable<tblA> source = myContext.TableA;
    
        if (criteriaA)
            source = source.Where(// something);
    
        if (criteriaB)
            source = source.Where(// something);
    
        // after processing criteria logic, determine type of view
        switch (byView)
        {
            case View1:
            {
                source = GetRecordsByView1(source);
                break;
            }
    
            //other case blocks
        }
    
        myGridView.DataSource = source;
    }
    

    无法格式化节点“OptionalValue” 作为SQL执行。

    我相信这是在下面的代码行中:

    Owner = owner.Select(o => o.LastName).DefaultIfEmpty()
    

    GroupJoin 作为一种扩展方法。

    3 回复  |  直到 9 年前
        1
  •  3
  •   diceguyd30    15 年前

    你说得对 Owner = owner.Select(o => o.LastName).DefaultIfEmpty() 是这条线引起了你的问题。我想到的最好的解决办法是这样的:

    var records = source.GroupJoin(myContext.TableB,
                      info => info.CustomerID,
                      owner => owner.CustomerID,
                      (info, owner) => new { info, owner }).ToList();
    records.Select(x => new
                      {
                          x.info.CustomerID,
                          Owner = x.owner.First() == null ? new string[] {} : x.owner.Select(o => o.LastName).ToArray(),
                          Store = x.info.Store,
                      })
                      .Select(record => new
                      {
                          record.CustomerID,
                          record.Owner,
                          record.Store,
                      });
    

    当然,这并不理想(你必须用“ToList”实现groupjoin),也许有更好的解决方案,但这对我很有效。你可能要玩一玩才能让它适合你,但我希望这能帮你一路走下去。

        2
  •  2
  •   IAbstract    15 年前

    首先……@布莱恩让我走上了正轨。以下是解决方案:

    var records = source
                  .GroupJoin(myContext.TableB,
                  info => info.CustomerID,
                  owner => owner.CustomerID,
                  (info, owner) => new
                  {
                      info,
                      Owner = owner.Select(o => o.LastName).First()
                  })
                  .Select(record => new
                  {
                      record.info.CustomerID,
                      record.Owner,
                      record.info.Store
                  });
    

        3
  •  -1
  •   Community Mohan Dere    9 年前

    查看此左外部连接示例: http://msdn.microsoft.com/en-us/library/bb397895.aspx

    相关样本:

    var query = from person in people
    join pet in pets on person equals pet.Owner into gj
    from subpet in gj.DefaultIfEmpty()
    select new { person.FirstName, PetName = (subpet == null ? String.Empty : subpet.Name) }
    

    其他人在此处使用DefaultIfEmpty时遇到了类似的错误: Max or Default? http://blog.appelgren.org/2008/05/15/linq-to-sql-aggregates-and-empty-results/

    哦。