Можно ли как-то проще?
От: MozgC США http://nightcoder.livejournal.com
Дата: 24.03.11 22:24
Оценка: 1 (1)
Есть таблицы
Suppliers { ID, Name, ... }
и
Custpercents { ID, CustomerID, SupplierID, Perc }

Все поля в этих таблицах NOT NULL.

Был такой запрос:

SELECT
  s.ID, s.Name, cp.Perc
FROM
  suppliers s 
    LEFT JOIN custpercents cp ON (cp.SupplierID = s.ID AND cp.CustomerID = ?CustomerID)
ORDER BY 
  s.Name

Соответственно если соответствующая строка в таблице custpercents не находилась, то вместо Perc возвращался null и именно это мне и надо было.

При переходе на linq я специально сделал чтобы генерировался именно LEFT JOIN, но вместо Perc оказывался не null, а 0 (член Perc объявлен как int).

Чтобы возвращался именно null, пришлось немного извратиться и написать такой запрос:

var q =
    from s in db.Suppliers
    join cp in db.Custpercents 
        on new { s.ID, CustomerID = (int)cbCustomers.SelectedValue } equals new { ID = cp.SupplierID, cp.CustomerID } into g
    from cp in g.DefaultIfEmpty() // to make left join
    orderby s.Name
    select new { s.ID, s.Name, Perc = Sql.AsSql((int?)cp.Perc) };

Можно ли как-то проще добиться цели?

Спасибо.
Re: Можно ли как-то проще?
От: MozgC США http://nightcoder.livejournal.com
Дата: 01.04.11 22:41
Оценка:
?
Re: Можно ли как-то проще?
От: IT Россия linq2db.com
Дата: 02.04.11 15:51
Оценка:
Здравствуйте, MozgC, Вы писали:

MC>Можно ли как-то проще добиться цели?


А как бы ты тоже самое делал на Linq 2 Objects?
Если нам не помогут, то мы тоже никого не пощадим.
Re[2]: Можно ли как-то проще?
От: MozgC США http://nightcoder.livejournal.com
Дата: 02.04.11 17:10
Оценка:
Здравствуйте, IT, Вы писали:

IT>А как бы ты тоже самое делал на Linq 2 Objects?


Наверное так:

var q =
    from s in suppliers
    join cp in custpercents 
        on new { s.ID, CustomerID = (int)cbCustomers.SelectedValue } equals new { ID = cp.SupplierID, cp.CustomerID } into g
    from cp in g.DefaultIfEmpty() // to make left join
    orderby s.Name
    select new { s.ID, s.Name, Perc = cp == null ? null : (int?)cp.Perc };

Но я подумал что в твоей реализации ты может быть придумал способ как сделать запись хотя бы немного удобнее (или может быть я что-то упускаю), нет?
Re[3]: Можно ли как-то проще?
От: Jack128  
Дата: 02.04.11 17:38
Оценка:
Здравствуйте, MozgC, Вы писали:

MC>Здравствуйте, IT, Вы писали:


IT>>А как бы ты тоже самое делал на Linq 2 Objects?


MC>Наверное так:


MC>
var q =
MC>    from s in suppliers
MC>    join cp in custpercents 
MC>        on new { s.ID, CustomerID = (int)cbCustomers.SelectedValue } equals new { ID = cp.SupplierID, cp.CustomerID } into g
MC>    from cp in g.DefaultIfEmpty() // to make left join
MC>    orderby s.Name
MC>    select new { s.ID, s.Name, Perc = cp == null ? null : (int?)cp.Perc };

MC>Но я подумал что в твоей реализации ты может быть придумал способ как сделать запись хотя бы немного удобнее (или может быть я что-то упускаю), нет?

проблема не bLToolkit, а в синтаксисе линка. В линке нету краткого синтаксиса для left join, соответственно и бл тулките его нету. Нет, IT наверное может изменить смысл _уже существующего_ синтаксиса, но ИМХО — это очень не желательно, потому что тогда возникнут разночтения между LinqToObject/LinkToSql и LinqToBlToolkit.

максимум, что можно — это написать примерно такой экстеншн метод:


    static class LeftJoinExtensions
    {
        public static IEnumerable<TResult> LeftJoin<T1, T2, TResult, TKey>(this IEnumerable<T1> t1, IEnumerable<T2> t2,
            Func<T1, TKey> t1KeySelector, Func<T2, TKey> t2KeySelector, Func<T1, T2, TResult> resultSelector)
        {
            var q =
                from item1 in t1
                join item2 in t2 on t1KeySelector(item1) equals t2KeySelector(item2) into g
                from item2 in g.DefaultIfEmpty()
                select resultSelector(item1, item2);
            return q;
        }
    }

            var table1 = new[] {1, 2, 4, 50};
            var table2 = new[] { 1, 3, 4, 50 };

            var q = table1.LeftJoin(table2, i => i, i => i, (i1, i2) => new {i1, i2});
            MessageBox.Show(string.Join(", ", q.Select(x => "(" + x.i1 + ", " + x.i2 + ")")));



тока мне кажется в большинстве случаев — в рукопашную лефт джойн делать — удобнее будет.
Re[3]: Можно ли как-то проще?
От: IT Россия linq2db.com
Дата: 02.04.11 17:39
Оценка:
Здравствуйте, MozgC, Вы писали:

MC>Наверное так:


MC>
var q =
MC>    from s in suppliers
MC>    join cp in custpercents 
MC>        on new { s.ID, CustomerID = (int)cbCustomers.SelectedValue } equals new { ID = cp.SupplierID, cp.CustomerID } into g
MC>    from cp in g.DefaultIfEmpty() // to make left join
MC>    orderby s.Name
MC>    select new { s.ID, s.Name, Perc = cp == null ? null : (int?)cp.Perc };

MC>Но я подумал что в твоей реализации ты может быть придумал способ как сделать запись хотя бы немного удобнее (или может быть я что-то упускаю), нет?

Как ты себе представляешь?
Если нам не помогут, то мы тоже никого не пощадим.
Re[4]: Можно ли как-то проще?
От: Jack128  
Дата: 02.04.11 17:42
Оценка:
Здравствуйте, Jack128, Вы писали:


Блин. В моем коде все Func<> нужно заменить на Expresion<Func<..>>.. по идее — это не на что не повлияет.
Re[4]: Можно ли как-то проще?
От: MozgC США http://nightcoder.livejournal.com
Дата: 08.04.11 02:23
Оценка:
Здравствуйте, IT, Вы писали:

IT>Как ты себе представляешь?


Может хотя бы как-то так:
var q =
    from s in db.Suppliers
    join cp in db.LeftJoin<Custpercent>()
        on new { s.ID, CustomerID = (int)cbCustomers.SelectedValue } equals new { ID = cp.SupplierID, cp.CustomerID }
    orderby s.Name
    select new { s.ID, s.Name, Perc = Sql.AsSql((int?)cp.Perc) };


PS. Может стоит в документации (твоей статье) подробнее рассмотреть примеры с left join? В частности написать, что можно использовать конструкцию
Perc = Sql.AsSql((int?)cp.Perc)
для получения nullable-значения, т.к. если писать (что логично для linq 2 objects)
Perc = cp == null ? null : (int?)cp.Perc
то это будет тянуть все поля таблицы.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.