有条件地加入LINQ

Jef*_*eff 4 c# linq

我想创建一个相当于a的LINQ join语句 Left Join

我的表设置如下:

Recipe
    RecipeID
    ...

Instruction
    RecipeID
    StepID
    SomeFlag
    ...
Run Code Online (Sandbox Code Playgroud)

等效SQL:

SELECT *
FROM Recipe r
LEFT JOIN Instruction i
    ON r.RecipeID = i.RecipeID
    AND SomeFlag > 0
Run Code Online (Sandbox Code Playgroud)

这是我到目前为止:

var tmp = db.Recipe
    .GroupJoin(
        db.Instruction,
        r => r.RecipeID,
        i => i.RecipeID,
        (r, i) => new {r, i},
        ???);
Run Code Online (Sandbox Code Playgroud)

首先,GroupJoin这种操作的正确选择是什么?据我所知,Join相当于SQL'Internal Join',而GroupJoin相当于'Left Join'.第二,获得我想要的结果的正确语法是什么?我一直在寻找,我似乎无法使用扩展方法找到合适的答案.

Céd*_*non 6

不要忘记阅读((GroupJoinMSDN http://msdn.microsoft.com/en-us/library/bb535047.aspxJoinMSDN http://msdn.microsoft.com/fr-fr/library/bb534675)的帮助.aspx)

的最后一个参数GroupJoinJoin是可选的(由过载),并且通常不使用.这是一个功能,允许您指定如何比较r.RecipeIDi.RecipeID.由于RecipeID必须是整数,使用默认比较器是一个不错的选择.所以让它:

var tmp = db.Recipe
    .Join(db.Instruction,
          r => r.RecipeID,
          i => i.RecipeID,
          (r, i) => new {r, i});
Run Code Online (Sandbox Code Playgroud)

现在你想要的是删除所有的指令SomeFlag > 0.加入前为什么不这样做呢?像这样:

var tmp = db.Recipe
    .Join(db.Instruction.Where(instruction => instruction.SomeFlag > 0),
          r => r.RecipeID,
          i => i.RecipeID,
          (r, i) => new {r, i});
Run Code Online (Sandbox Code Playgroud)

更新

@usr完美地评论说Join执行INNER JOIN.

您可能已经注意到,LINQ没有针对INNER,OUTER,LEFT,RIGHT联接的不同方法.要了解特定SQL连接的等效LINQ,您可以在MSDN上找到帮助(http://msdn.microsoft.com/en-us/library/vstudio/bb397676.aspx).

var tmp = from recipe in Recipes
          join instruction in
              from instruction in Instructions
              where instruction.SomeFlag > 0
              select instruction
          on recipe.RecipeID equals instruction.RecipeID into gj
          from instruction in gj.DefaultIfEmpty()
          select new
          {
              recipe,
              instruction
          };
Run Code Online (Sandbox Code Playgroud)

使用扩展方法这是一个丑陋的解决方案:

var tmp = Recipes.GroupJoin(Instructions.Where(instruction => instruction.SomeFlag > 0),
                            recipe => recipe.RecipeID,
                            instruction => instruction.RecipeID,
                            (recipe, gj) => new { recipe, gj })
                 .SelectMany(@t => @t.gj.DefaultIfEmpty(), 
                             (@t, instruction) => new
                             {
                                 @t.recipe,
                                 instruction
                             });
Run Code Online (Sandbox Code Playgroud)