2010-11-06 53 views
3

我一直在尝试使用Join和GroupJoin方法。问题看起来很简单。鉴于TableATableB的数据地图这样的:正确加入/组加入执行

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

...我使用TableA作为我的主表,并想加入一个领域,在CustomerIDTableB检索[TableB].[LastName]

应该不困难,除非我难以使结果正常工作。无论TableB中匹配的CustomerID如何,TableA都有我想要的记录。听起来像一个左连接 - 所以,阅读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; 
} 

的问题:我接收以下错误:

Could not format node 'OptionalValue' for execution as SQL.

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

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

我在这里做错了什么?我必须写作GroupJoin作为扩展方法。

回答

2

第一...... @布赖恩让我开始了正确的轨道。这里是解决方案:

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 
       }); 

这为我提供了所需的确切结果...

-1

看看这个左外连接例子: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) } 

你可以加入结果为GJ,然后使用DefaultIfEmpty创建外连接的情况下,仍能获得你想要的结果。 Max or Default? http://blog.appelgren.org/2008/05/15/linq-to-sql-aggregates-and-empty-results/

HTH:

别人利用这里得到DefaultIfEmpty类似的错误。

+0

的问题是,我必须写我的'Join'作为一个扩展方法。我不能写成LINQ语句。 – IAbstract 2010-11-08 15:15:43

3

你是对的,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”的群组加入),并有可能是一个更好的解决方案,但已经为我工作。你可能需要花一点时间才能让它适合你,但我希望这可以帮助你一路顺风。

+0

这看起来很有希望。我确实看到它看起来似乎没有实现数据 - 我开始明白这一点。删除'DefaultIfEmpty()'后,查询通过,但所有者结果为空。我进入结果,业主姓在那里,但埋葬。所以我知道我很接近......谢谢。 – IAbstract 2010-11-08 16:39:02

+0

+1让我的思维走上正轨。 – IAbstract 2010-11-08 17:10:46