我有两个名为CountryMobility的对象,我认为我需要与一个完整的外连接组合。我怎么能用linq做到这一点?
public class CountryMobility
{
public string countryCode { get; set; }
public int inbound { get; set; }
public int outbound { get; set; }
}
我想结合其中两个对象:
inboundStudents:
countryCode | inbound | outbound
EG | 2 | 0
CA | 3 | 0
CH | 5 | 0
outboundStudents:
countryCode | inbound | outbound
PE | 0 | 1
CA | 0 | 4
CH | 0 | 5
-
-
-
-
V
combinedStudents:
countryCode | inbound | outbound
PE | 0 | 1
CA | 3 | 4
CH | 5 | 5
EG | 2 | 0
我尝试了以下linq语句,但未能找出正确的语法。我目前正在接收语法错误 两个语句中都有temp.DefaultIfEmpty(new {first.ID,inbound = 0,outbound = 0})。
var leftOuterJoin =
from first in inboundActivities
join last in outboundActivities
on first.countryCode equals last.countryCode
into temp
from last in temp.DefaultIfEmpty
(new { first.countryCode, inbound = 0, outbound=0 })
select new CountryMobility
{
countryCode = first.countryCode,
inbound = first.inbound,
outbound = last.outbound,
};
var rightOuterJoin =
from last in outboundActivities
join first in inboundActivities
on last.countryCode equals first.countryCode
into temp
from first in temp.DefaultIfEmpty
(new { last.countryCode, inbound = 0, outbound = 0 })
select new CountryMobility
{
countryCode = last.countryCode,
inbound = first.inbound,
outbound = last.outbound,
};
var fullOuterJoin = leftOuterJoin.Union(rightOuterJoin);
答案 0 :(得分:1)
了解您的最新信息。在我看来,你可以做一些更简单的事情。即您随后按国家/地区代码分组的UNION ALL
。
可以使用UNION ALL
方法创建Concat
。
下面的示例适用于我(在内存集合中使用)。查询显示在Run
方法中。
public class CountryMobility
{
public string countryCode { get; set; }
public int inbound { get; set; }
public int outbound { get; set; }
}
public static class JoinedMobilityQuery
{
static CountryMobility[] inbound = {
new CountryMobility() { countryCode = "EG", inbound = 2 },
new CountryMobility() { countryCode = "CA", inbound = 3 },
new CountryMobility() { countryCode = "CH", inbound = 5 },
};
static CountryMobility[] outbound = {
new CountryMobility() { countryCode = "PE", outbound = 1 },
new CountryMobility() { countryCode = "CA", outbound = 4 },
new CountryMobility() { countryCode = "CH", outbound = 6 },
};
static IQueryable<CountryMobility> Inbound()
{
return inbound.AsQueryable();
}
static IQueryable<CountryMobility> Outbound()
{
return outbound.AsQueryable();
}
public static void Run()
{
var transfers = from t in Inbound().Concat(Outbound())
group t by t.countryCode into g
select new CountryMobility() {
countryCode = g.Key,
inbound = g.Sum(x => x.inbound),
outbound = g.Sum(x => x.outbound),
};
foreach (var transfer in transfers)
Console.WriteLine("{0}\t{1}\t{2}", transfer.countryCode, transfer.inbound, transfer.outbound);
}
}
答案 1 :(得分:1)
您的DefaultIfEmpty正在解决错误,因为您正在定义一个匿名对象,但您正在select语句中创建带有stronly类型的对象。它们都必须属于同一类型。
所以定义一个这样的默认对象:
var defaultActivity = new CountryMobility() { countryCode = String.Empty, outbound = 0, inbound = 0 };
在此之后,在DefaultIfEmpty()方法中使用它:
from last in temp.DefaultIfEmpty(defaultActivity)
select new CountryMobility
{
//...
};
最后但并非最不重要的是,你必须做一个groupby来获得所需的结果:
var fullOuterJoin = leftOuterJoin.Union(rightOuterJoin)
.GroupBy (oj => oj.countryCode)
.Select (oj => oj.FirstOrDefault());
输出:
完整演示代码:
答案 2 :(得分:0)
你可以这样做
List<CountryMobility> inboundStudents = new List<CountryMobility>{
new CountryMobility { countryCode="EG", inbound=2, outbound = 0},
new CountryMobility { countryCode="CA", inbound=3, outbound = 0},
new CountryMobility { countryCode="CH", inbound=5, outbound = 0}};
List<CountryMobility> outboundStudents = new List<CountryMobility>{
new CountryMobility { countryCode="PE", inbound=0, outbound = 1},
new CountryMobility { countryCode="CA", inbound=0, outbound = 4},
new CountryMobility { countryCode="CH", inbound=0, outbound = 5}};
var joinedList = inboundStudents.Concat(outboundStudents).GroupBy(item => new { item.countryCode});
var result = joinedList.Select(x => new
{
countryCode = x.Key.countryCode,
inbound = x.Sum(i => i.inbound),
outbound = x.Sum(i => i.outbound)
});