你写的语句仅仅是左外连接,而你要的结果却是左外连接和右外连接的交集(以user_id为键做比较)。
当然通常我们不会这样做,因为太低效。
一个简单点的办法是先取两个list的user_id做并集运算得到所有的主键,然后依据主键进行子查询。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
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<int>,里面的值是{1,2,3,4,5}。对其中每一个值id,在list1和list2上比较user_id==id得到i1和i2。根据i1和i2是否为空决定该如何select结果集。
等价的查询子句语法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
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中出现的记录即可。
1
2
3
4
5
6
7
8
9
10
11
|
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
});
|
等价的查询符语法:
1
2
3
4
5
6
7
8
9
10
11
|
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
}));
|
还有其他几种方式可以满足你的需要,这里就不过多解释了。有问题请追问。