Выборка иерархии объектов с помощью BLT LINQ
От: Spaider Верблюд  
Дата: 01.08.11 11:08
Оценка:
Здравствуйте!

Есть задача, вернуть 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>>
--
К вашим услугам,
Re: Выборка иерархии объектов с помощью BLT LINQ
От: rameel https://github.com/rsdn/CodeJam
Дата: 01.08.11 13:32
Оценка: 7 (2)
Здравствуйте, 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>>
Re[2]: Выборка иерархии объектов с помощью BLT LINQ
От: MozgC США http://nightcoder.livejournal.com
Дата: 15.09.11 22:37
Оценка:
rameel,

при таком запросе получится SQL типа
SELECT ... FROM addresses INNER JOIN persons ON ...

и не будут выбраны люди у которых не указан адрес.

А как сделать чтобы все-таки получился запрос типа
SELECT ... FROM persons LEFT JOIN addresses ON ...

?
Re[3]: Выборка иерархии объектов с помощью BLT LINQ
От: rameel https://github.com/rsdn/CodeJam
Дата: 16.09.11 04:46
Оценка:
Здравствуйте, 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>>
Re[4]: Выборка иерархии объектов с помощью BLT LINQ
От: rameel https://github.com/rsdn/CodeJam
Дата: 16.09.11 04:59
Оценка:
Здравствуйте, rameel, Вы писали:

Забыл исправить
            select new
                {
                    p.ID,
                    p.FirstName,
                    p.LastName,
                    Address = a
                }).AsEnumerable()
... << RSDN@Home 1.2.0 alpha 5 rev. 1495>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.