Здравствуйте!
Есть задача, вернуть JSON с простой структурой объектов: массив объектов, у каждого из которых есть массив подчиненных объектов. Отношение один ко многим.
Для наглядности, пусть это будут Person и Address (т.е. у одного чела может быть несколько явок
)
Вопрос 1: можно ли написать один LINQ-запрос, чтобы возвращался IEnumerable с анонимным типом, среди свойств которого был бы IEnumerable со свойствами из Address:
...
select new {
person.FirstName,
person.LastName
...
Addresses = ...
}
Что-то у меня не получается, как я ни пробовал. От некоторых вариантов плохеет парсеру BLT во время выполнения запроса (4.0, 4.1 пока не пробовал).
Вопрос 2: не многого ли я хочу. Может, правильнее было бы получить все результаты простеньким join'ом а потом склепать нужные объекты в цикле foreach?
Понятно, что вопрос бОльшей частью по LINQ, но мне интересно именно в связке с BLT.
Прошу прощения, если написал ересь, никак до конца не перестрою свой закостенелый мозг на мышление в терминах LINQ
... << RSDN@Home 1.2.0 alpha 5 rev. 1514>>
Здравствуйте, Spaider, Вы писали:
S>Здравствуйте!
S>Есть задача, вернуть JSON с простой структурой объектов: массив объектов, у каждого из которых есть массив подчиненных объектов. Отношение один ко многим.
S>Для наглядности, пусть это будут Person и Address (т.е. у одного чела может быть несколько явок )
S>Вопрос 1: можно ли написать один LINQ-запрос, чтобы возвращался IEnumerable с анонимным типом, среди свойств которого был бы IEnumerable со свойствами из Address:
S>Что-то у меня не получается, как я ни пробовал. От некоторых вариантов плохеет парсеру BLT во время выполнения запроса (4.0, 4.1 пока не пробовал).
using (var db = GetDbManager())
{
var q =
from r in (
from a in db.GetTable<Address>()
select new
{
a.Person.ID,
a.Person.FirstName,
a.Person.LastName,
Address = a
}).AsEnumerable()
group r by new
{
r.ID,
r.FirstName,
r.LastName
}
into g
select new
{
g.Key.ID,
g.Key.FirstName,
g.Key.LastName,
Adresses = from a in g select a.Address
};
foreach (var p in q)
{
Console.WriteLine("{0} {1}", p.FirstName, p.LastName);
foreach (var a in p.Adresses)
Console.WriteLine("\t{0}", a.City);
}
}
[TableName("Persons")]
public class Person
{
[PrimaryKey, Identity]
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
[Association(ThisKey = "ID", OtherKey = "ID", CanBeNull = true)]
public List<Address> Addresses { get; set; }
}
[TableName("Addresses")]
public class Address
{
[PrimaryKey, Identity]
public int ID { get; set; }
public string City { get; set; }
public int PersonID { get; set; }
[Association(ThisKey = "PersonID", OtherKey = "ID", CanBeNull = false)]
public Person Person { get; set; }
}
... << RSDN@Home 1.2.0 alpha 5 rev. 1495>>
rameel,
при таком запросе получится SQL типа
SELECT ... FROM addresses INNER JOIN persons ON ...
и не будут выбраны люди у которых не указан адрес.
А как сделать чтобы все-таки получился запрос типа
SELECT ... FROM persons LEFT JOIN addresses ON ...
?
Здравствуйте, MozgC, Вы писали:
MC>при таком запросе получится SQL типа
SELECT ... FROM addresses INNER JOIN persons ON ...
MC>и не будут выбраны люди у которых не указан адрес.
MC>А как сделать чтобы все-таки получился запрос типа
SELECT ... FROM persons LEFT JOIN addresses ON ...
MC>?
Примерно так
using (var db = GetDbManager())
{
var q =
from r in (
from p in db.GetTable<Person>() // <<<<
from a in p.Addresses.DefaultIfEmpty() // <<<<
select new
{
a.Person.ID,
a.Person.FirstName,
a.Person.LastName,
Address = a
}).AsEnumerable()
group r by new
{
r.ID,
r.FirstName,
r.LastName
}
into g
select new
{
g.Key.ID,
g.Key.FirstName,
g.Key.LastName,
Adresses = from p in g where p.Address != null select p.Address // <<<<
};
}
или так, но длинно
from p in db.GetTable<Person>()
join a in db.GetTable<Address>() on p.AddressID equals a.ID into g
from a in g.DefaultIfEmpty()
....
... << RSDN@Home 1.2.0 alpha 5 rev. 1495>>
Здравствуйте, rameel, Вы писали:
Забыл исправить
select new
{
p.ID,
p.FirstName,
p.LastName,
Address = a
}).AsEnumerable()
... << RSDN@Home 1.2.0 alpha 5 rev. 1495>>