0

假设我有以下表格:

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 中执行此操作?

4

3 回答 3

1

不确定“空值”,因为您没有在伪代码中提供任何可为空的属性。但是我认为 LINQ 查询会/可能是这样的:

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

var blocksWithNoBidsInModuleBlocks = blocks
   .Where(b => !moduleBlocks.Select(mb => mb.BID).Contains(b.BID)).ToList();
于 2012-08-20T08:34:45.880 回答
1

如果您乐于在客户端执行此操作而不是将其转换为 SQL,则可以修改MoreLinq 的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);
    }
}  
于 2012-08-20T09:00:29.097 回答
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;

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

于 2012-08-20T09:10:45.223 回答