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 joinorderby s.Name
select new { s.ID, s.Name, Perc = Sql.AsSql((int?)cp.Perc) };
Здравствуйте, 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 joinorderby s.Name
select new { s.ID, s.Name, Perc = cp == null ? null : (int?)cp.Perc };
Но я подумал что в твоей реализации ты может быть придумал способ как сделать запись хотя бы немного удобнее (или может быть я что-то упускаю), нет?
Здравствуйте, 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 + ")")));
тока мне кажется в большинстве случаев — в рукопашную лефт джойн делать — удобнее будет.
Здравствуйте, 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>Но я подумал что в твоей реализации ты может быть придумал способ как сделать запись хотя бы немного удобнее (или может быть я что-то упускаю), нет?
Как ты себе представляешь?
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, 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)