使用LINQ进行条件连接
本文关键字:条件 连接 LINQ 使用 | 更新日期: 2023-09-27 17:55:04
我想创建一个相当于Left Join
的LINQ连接语句
我的表设置如下:
Recipe
RecipeID
...
Instruction
RecipeID
StepID
SomeFlag
...
等价的SQL:
SELECT *
FROM Recipe r
LEFT JOIN Instruction i
ON r.RecipeID = i.RecipeID
AND SomeFlag > 0
这是我目前为止写的:
var tmp = db.Recipe
.GroupJoin(
db.Instruction,
r => r.RecipeID,
i => i.RecipeID,
(r, i) => new {r, i},
???);
首先,GroupJoin
是这类操作的正确选择吗?据我所知,Join相当于SQL的"内连接",GroupJoin相当于"左连接"。其次,获得我想要的结果的正确语法是什么?我一直在寻找一段时间,我似乎不能找到一个合适的答案使用扩展方法。
不要忘记阅读来自(GroupJoin
: MSDN http://msdn.microsoft.com/en-us/library/bb535047.aspx和Join
MSDN http://msdn.microsoft.com/fr-fr/library/bb534675.aspx)的帮助
GroupJoin
和Join
的最后一个参数是可选的(通过重载),通常不使用。它是一个函数,允许您指定如何比较r.RecipeID
和i.RecipeID
。因为RecipeID
必须是一个整数,所以使用默认比较器是一个不错的选择。输入:
var tmp = db.Recipe
.Join(db.Instruction,
r => r.RecipeID,
i => i.RecipeID,
(r, i) => new {r, i});
现在你要做的是删除所有具有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});
更新@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
};
使用扩展方法是一个有点丑陋的解决方案:
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
});
如果我没有理解你,请告诉我,但是这个扩展方法返回的结果与你在sql中提供的结果相同。
public static IEnumerable<ResultType> GetLeftJoinWith(this IEnumerable<Recipe>, IEnumerable<Instructions> ins)
{
var filteredInstructions = ins.Where(x => x.SomeFlag > 0);
var res = from r in rec
join tmpIns in filteredInstructions on r.RecipeID equals t.RecipeID into instructions
from instruction in instructions.DefaultIfEmpty()
select new { r, instruction };
return res;
}
try this
var model = db.Recipe
.GroupJoin(db.Instructions.Where(instruction => instruction.SomeFlag > 0),r => r.RecipeID,i => i.RecipeID, (r, i) => new { Recipe = r, Instructions = i })
.SelectMany(t => t.Instructions.DefaultIfEmpty(),(t, Instructions) => new
{
Recipe = t.Recipe,
Instructions = Instructions
});