Linq选择所有未找到的linq

时间:2012-08-20 08:17:05

标签: c# .net linq

假设我有以下表格:

class Module
{
    long MID    // PK
    string Name
}

class ModuleBlock
{
    long MID      // FK
    long BID      // FK
}

class Block
{
    long BID      // PK
    string Info
}

我想在ModuleBlocks中选择所有没有BID的块。

我该如何进行此查询?

我很确定这是在BID上使用ModuleBlocks连接块并检查空值但是如何在LINQ中执行此操作?

3 个答案:

答案 0 :(得分:1)

由于您未在伪代码中提供任何可为空的属性,因此不确定'nulls'。但是我认为LINQ查询可能是这样的:

List<Module> modules = ...
List<ModuleBlock> moduleBlocks = ...
List<Block> blocks = ...

var blocksWithNoBidsInModuleBlocks = blocks
   .Where(b => !moduleBlocks.Select(mb => mb.BID).Contains(b.BID)).ToList();

答案 1 :(得分:1)

如果您乐意在客户端执行此操作而不是将其转换为SQL,则可以修改MoreLinq's ExceptBy方法以处理两种不同类型的序列。

然后你可以打电话

var modulelessBlocks =
 allBlocks.Except(
     allModuleBlocks,
     block => block.MID,
     moduleblock => moduleblock.MID);

这样做的好处是只能迭代每个源一次。

以下是修改过的迭代器的示例 - 您必须修改其他方法以匹配:

private static IEnumerable<TSource> ExceptByImpl<TSource, TSecond, TKey>(
    this IEnumerable<TSource> first,
    IEnumerable<TSecond> second,
    Func<TSource, TKey> keySelectorSource,
    Func<TSecond, TKey> keySelectorSecond,
    IEqualityComparer<TKey> keyComparer)
{
    HashSet<TKey> keys = new HashSet<TKey>(
        second.Select(keySelectorSecond),
        keyComparer);
    foreach (var element in first)
    {
        TKey key = keySelectorSource(element);
        if (keys.Contains(key))
        {
            continue;
        }
        yield return element;
        keys.Add(key);
    }
}  

答案 2 :(得分:1)

这里只使用连接这是一种相当简单的方法:

var bids =
    from m in modules
    join mb in moduleBlocks on m.MID equals mb.MID
    select mb.BID;

var bs =
    from b in blocks
    join bid in bids on b.BID equals bid into gbids
    where !gbids.Any()
    select b;

第二个查询为您提供所需的结果。