如何在c# LINQ中执行左外连接到对象而不使用join-on-equal -into子句?有办法用where子句来实现吗?
正确的问题:
内连接很简单,我有一个这样的解决方案
List<JoinPair> innerFinal = (from l in lefts from r in rights where l.Key == r.Key
select new JoinPair { LeftId = l.Id, RightId = r.Id})
但是对于左外连接,我需要一个解决方案。我的是这样的,但它不工作
List< JoinPair> leftFinal = (from l in lefts from r in rights
select new JoinPair {
LeftId = l.Id,
RightId = ((l.Key==r.Key) ? r.Id : 0
})
其中JoinPair是一个类:
public class JoinPair { long leftId; long rightId; }
下面是一个版本的扩展方法解决方案,使用IQueryable代替IEnumerable
public class OuterJoinResult<TLeft, TRight>
{
public TLeft LeftValue { get; set; }
public TRight RightValue { get; set; }
}
public static IQueryable<TResult> LeftOuterJoin<TLeft, TRight, TKey, TResult>(this IQueryable<TLeft> left, IQueryable<TRight> right, Expression<Func<TLeft, TKey>> leftKey, Expression<Func<TRight, TKey>> rightKey, Expression<Func<OuterJoinResult<TLeft, TRight>, TResult>> result)
{
return left.GroupJoin(right, leftKey, rightKey, (l, r) => new { l, r })
.SelectMany(o => o.r.DefaultIfEmpty(), (l, r) => new OuterJoinResult<TLeft, TRight> { LeftValue = l.l, RightValue = r })
.Select(result);
}
class Program
{
List<Employee> listOfEmp = new List<Employee>();
List<Department> listOfDepart = new List<Department>();
public Program()
{
listOfDepart = new List<Department>(){
new Department { Id = 1, DeptName = "DEV" },
new Department { Id = 2, DeptName = "QA" },
new Department { Id = 3, DeptName = "BUILD" },
new Department { Id = 4, DeptName = "SIT" }
};
listOfEmp = new List<Employee>(){
new Employee { Empid = 1, Name = "Manikandan",DepartmentId=1 },
new Employee { Empid = 2, Name = "Manoj" ,DepartmentId=1},
new Employee { Empid = 3, Name = "Yokesh" ,DepartmentId=0},
new Employee { Empid = 3, Name = "Purusotham",DepartmentId=0}
};
}
static void Main(string[] args)
{
Program ob = new Program();
ob.LeftJoin();
Console.ReadLine();
}
private void LeftJoin()
{
listOfEmp.GroupJoin(listOfDepart.DefaultIfEmpty(), x => x.DepartmentId, y => y.Id, (x, y) => new { EmpId = x.Empid, EmpName = x.Name, Dpt = y.FirstOrDefault() != null ? y.FirstOrDefault().DeptName : null }).ToList().ForEach
(z =>
{
Console.WriteLine("Empid:{0} EmpName:{1} Dept:{2}", z.EmpId, z.EmpName, z.Dpt);
});
}
}
class Employee
{
public int Empid { get; set; }
public string Name { get; set; }
public int DepartmentId { get; set; }
}
class Department
{
public int Id { get; set; }
public string DeptName { get; set; }
}
输出