你写的语句仅仅是左外连接,而你要的结果却是左外连接和右外连接的交集(以user_id为键做比较)。
当然通常我们不会这样做,因为太低效。
一个简单点的办法是先取两个list的user_id做并集运算得到所有的主键,然后依据主键进行子查询。
var tmp1 = list1
.Select(i => i.user_id)
.Union(list2.Select(i => i.user_id))
.ToList()
.Select(id =>
{
var i1 = list1.FirstOrDefault(i => i.user_id == id);
var i2 = list2.FirstOrDefault(i => i.user_id == id);
return new
{
user_id = i1 == null ? i2.user_id : i1.user_id,
num1 = i1 == null ? 0 : i1.num1,
pic = i1 == null ? 0 : i1.pic,
num2 = i2 == null ? 0 : i2.num2,
send = i2 == null ? 0 : i2.send
};
});
稍微解释下。首先我们拿到list1和list2的所有user_id,然后使用Union扩展方法做并集运算得到匿名IEnumerable
等价的查询子句语法:
var tmp11 = from id in
(from i1 in list1 select i1.user_id)
.Union((from i2 in list2 select i2.user_id))
.ToList()
let r1 = (from i1 in list1 where i1.user_id == id select i1)
.FirstOrDefault()
let r2 = (from i2 in list2 where i2.user_id == id select i2)
.FirstOrDefault()
select new
{
user_id = r1 == null ? r2.user_id : r1.user_id,
num1 = r1 == null ? 0 : r1.num1,
pic = r1 == null ? 0 : r1.pic,
num2 = r2 == null ? 0 : r2.num2,
send = r2 == null ? 0 : r2.send
};
如果想利用现有的代码,我们还可以为newList补上它缺失的记录。检查一下list2中所有user_id没有在list1中出现的记录即可。
newList = newList.Concat(
from b in list2
where !(from a in list1 select a.user_id).Contains(b.user_id)
select new
{
user_id = b.user_id,
num1 = 0,
pic = 0,
num2 = b.num2,
send = b.send
});
等价的查询符语法:
newList = newList.Concat(
list2
.Where(i2 => !list1.Select(i1 => i1.user_id).Contains(i2.user_id))
.Select(b => new
{
user_id = b.user_id,
num1 = 0,
pic = 0,
num2 = b.num2,
send = b.send
}));
还有其他几种方式可以满足你的需要,这里就不过多解释了。有问题请追问。