Linq 用枢轴填充嵌套对象
Linq to fill nested objects with pivot
我有如下两个表格
Person{
int id;
string name;
}
PersonAddresses{
int id;
string AddressType;
string City;
string State;
}
这里AddressType指定"BusinessAddress","HomeAddress"等。
我想得到如下结果。
class PersonData{
int id;
string Name;
Address BusinessAddress;
Address HomeAddress;
...
}
class Address{
string City;
string State;
}
任何人都可以告诉我如何使用 LINQ 执行此操作而无需多选吗?
我能想出的最简单的查询是这样的
// by doing groupby and select you choose only one address of the type,
// if a person has many.
// If you can be sure that each person has only one address of each type
// then you can simplify these queries a little bit.
IQueryable<PersonAddresses> homeAddresses = from address in addresses
where address.AddressType == "HomeAddress"
group address by address.id into g
select g.First();
IQueryable<PersonAddresses> businessAddresses = from address in addresses
where address.AddressType == "BusinessAddress"
group address by address.id into g
select g.First();
IQueryable<PersonData> data = from person in persons
join tmp1 in homeAddresses on person.id equals tmp1.id into ha
join tmp2 in businessAddresses on person.id equals tmp2.id into ba
from homeAddress in ha.DefaultIfEmpty()
from businessAddress in ba.DefaultIfEmpty()
select new PersonData {
id = person.id,
Name = person.name,
HomeAddress = homeAddress == null
? null
: new Address {
City = homeAddress.City,
State = homeAddress.State
},
BusinessAddress = businessAddress == null
? null
: new Address {
City = businessAddress.City,
State = businessAddress.State
},
};
您可以获得这样的结果 sql 查询:
string sql = ((System.Data.Entity.Core.Objects.ObjectQuery) data).ToTraceString();
你可以在这里和那里进行简化,但它的意义不大,因为你通常不能完全期望你的数据是正确的——有些列表有重复,有些值缺失,所以我的查询涵盖了极端情况。
您正在寻找的是 Group join 结合子选择以从组中获取家庭和公司地址:
var query =
from person in Persons
join address in PersonAddresses
on person.id equals address.id into personData
select new PersonData()
{
id = person.id,
Name = person.name,
HomeAddress = (
from data in personData
where data.AddressType == "HomeAddress"
select new Address()
{
City = data.City,
State = data.State
}).FirstOrDefault(),
BusinessAddress = (
from data in personData
where data.AddressType == "BusinessAddress"
select new Address()
{
City = data.City,
State = data.State
}).FirstOrDefault(),
};
这作为单个 SQL 查询运行:
SELECT
[Extent1].[id] AS [id],
[Extent1].[name] AS [name],
[Limit1].[id] AS [id1],
[Limit1].[City] AS [City],
[Limit1].[State] AS [State],
[Limit2].[id] AS [id2],
[Limit2].[City] AS [City1],
[Limit2].[State] AS [State1]
FROM [dbo].[Person] AS [Extent1]
OUTER APPLY (SELECT TOP (1)
[Extent2].[id] AS [id],
[Extent2].[City] AS [City],
[Extent2].[State] AS [State]
FROM [dbo].[PersonAddresses] AS [Extent2]
WHERE ([Extent1].[id] = [Extent2].[id]) AND (N'HomeAddress' = [Extent2].[AddressType]) ) AS [Limit1]
OUTER APPLY (SELECT TOP (1)
[Extent3].[id] AS [id],
[Extent3].[City] AS [City],
[Extent3].[State] AS [State]
FROM [dbo].[PersonAddresses] AS [Extent3]
WHERE ([Extent1].[id] = [Extent3].[id]) AND (N'BusinessAddress' = [Extent3].[AddressType]) ) AS [Limit2]
我有如下两个表格
Person{
int id;
string name;
}
PersonAddresses{
int id;
string AddressType;
string City;
string State;
}
这里AddressType指定"BusinessAddress","HomeAddress"等。 我想得到如下结果。
class PersonData{
int id;
string Name;
Address BusinessAddress;
Address HomeAddress;
...
}
class Address{
string City;
string State;
}
任何人都可以告诉我如何使用 LINQ 执行此操作而无需多选吗?
我能想出的最简单的查询是这样的
// by doing groupby and select you choose only one address of the type,
// if a person has many.
// If you can be sure that each person has only one address of each type
// then you can simplify these queries a little bit.
IQueryable<PersonAddresses> homeAddresses = from address in addresses
where address.AddressType == "HomeAddress"
group address by address.id into g
select g.First();
IQueryable<PersonAddresses> businessAddresses = from address in addresses
where address.AddressType == "BusinessAddress"
group address by address.id into g
select g.First();
IQueryable<PersonData> data = from person in persons
join tmp1 in homeAddresses on person.id equals tmp1.id into ha
join tmp2 in businessAddresses on person.id equals tmp2.id into ba
from homeAddress in ha.DefaultIfEmpty()
from businessAddress in ba.DefaultIfEmpty()
select new PersonData {
id = person.id,
Name = person.name,
HomeAddress = homeAddress == null
? null
: new Address {
City = homeAddress.City,
State = homeAddress.State
},
BusinessAddress = businessAddress == null
? null
: new Address {
City = businessAddress.City,
State = businessAddress.State
},
};
您可以获得这样的结果 sql 查询:
string sql = ((System.Data.Entity.Core.Objects.ObjectQuery) data).ToTraceString();
你可以在这里和那里进行简化,但它的意义不大,因为你通常不能完全期望你的数据是正确的——有些列表有重复,有些值缺失,所以我的查询涵盖了极端情况。
您正在寻找的是 Group join 结合子选择以从组中获取家庭和公司地址:
var query =
from person in Persons
join address in PersonAddresses
on person.id equals address.id into personData
select new PersonData()
{
id = person.id,
Name = person.name,
HomeAddress = (
from data in personData
where data.AddressType == "HomeAddress"
select new Address()
{
City = data.City,
State = data.State
}).FirstOrDefault(),
BusinessAddress = (
from data in personData
where data.AddressType == "BusinessAddress"
select new Address()
{
City = data.City,
State = data.State
}).FirstOrDefault(),
};
这作为单个 SQL 查询运行:
SELECT
[Extent1].[id] AS [id],
[Extent1].[name] AS [name],
[Limit1].[id] AS [id1],
[Limit1].[City] AS [City],
[Limit1].[State] AS [State],
[Limit2].[id] AS [id2],
[Limit2].[City] AS [City1],
[Limit2].[State] AS [State1]
FROM [dbo].[Person] AS [Extent1]
OUTER APPLY (SELECT TOP (1)
[Extent2].[id] AS [id],
[Extent2].[City] AS [City],
[Extent2].[State] AS [State]
FROM [dbo].[PersonAddresses] AS [Extent2]
WHERE ([Extent1].[id] = [Extent2].[id]) AND (N'HomeAddress' = [Extent2].[AddressType]) ) AS [Limit1]
OUTER APPLY (SELECT TOP (1)
[Extent3].[id] AS [id],
[Extent3].[City] AS [City],
[Extent3].[State] AS [State]
FROM [dbo].[PersonAddresses] AS [Extent3]
WHERE ([Extent1].[id] = [Extent3].[id]) AND (N'BusinessAddress' = [Extent3].[AddressType]) ) AS [Limit2]