Целесообразно ли использовать LINQ to SQL для такой задачи?
От: Аноним  
Дата: 03.08.10 13:33
Оценка:
Hi,

У нас в программе используется контрол ComponentOne Query™ 8.0
С помощью него пользователь в программе может выбрать таблички, колонки в этих табличках, указать различные условия (типа where) и выбрать интересующие его данные из БД.
Этот контрол является query builder'ом — он по заранее заданной xml-схеме таблиц, связей и по выбору пользователя позволяет строить sql-select.
Этот контрол умеет работать с таблицами и вьюхами. Нам сейчас стало не хватать функциональности этого контрола. В частности нужно джойнить на sql-function...

Первая идея — заменить контрол.
Нашёл парочку:
http://www.activequerybuilder.com/screenshots.html
http://devtools.korzh.com/eq/dotnet

Оба не подошли по ряду причин.
Может кто-то посоветует другой query builder контрол с простым юзер интерфейсом?

Как вариант подумываем написать свой контрол.
Решил попробовать использовать Linq to Sql для этого.
Нашёл библиотеку dynamic LINQ, с помощь неё очень удобно формировать динамические WHERE и SELECT.
Проблема возникла с Join.
Например есть таблицы Customers и Products. Есть sql-function fn_GetProducts(), которая выбирает все продукты. Для примера будем считать, что связь один к одному: один Customer — один Product.
Выборка Customers Left join Products будет выглядеть так:
var a = db.Customers
  .GroupJoin(db.fn_GetProducts(), c => c.ID, p => p.ID, (c, ps) => new {c.ID, c, ps})
  .SelectMany(@t => @t.ps.DefaultIfEmpty(), (@t, p) => new {@t.c.ID, @t.c.Name, p.Description});

Мне надо как-то цеплять join'ы динамически. То есть что-то похожее на:
Сделать Linq для выбора Customers. Что-то типа IQueryable<Customer> q = db.Customers.Select(c => c);
IF (пользователь чекнул "вместе с продуктами")
{
  тут добавить join на fn_GetProducts()
}
IF (пользователь чекнул "вместе с ещё чем-то")
{
  тут добавить join на fn_GetЕщёЧтото()
}
и т.д.

Как такое можно реализовать? И можно ли?
И в целом как думаете, стоит использовать LINQ to SQL для этих целей?

Спасибо. Если не за ответ, то хотя б за то, что дочитали до конца
Re: Целесообразно ли использовать LINQ to SQL для такой зада
От: Neco  
Дата: 04.08.10 05:06
Оценка:
А>Мне надо как-то цеплять join'ы динамически. То есть что-то похожее на:
ну where условия так точно можно добавлять. А раз можно их, то почему не всё остальное?
Единственное надо определиться с возвращаемым таким методом типом — видимо он должен быть "на все случаи жизни".

А>И в целом как думаете, стоит использовать LINQ to SQL для этих целей?

я б сказал, что именно для этого и стоит. Имхо, если бы не было динамических построений SQL можно было бы обходиться вообще безо всяких ORM и писать запросы ручками.
всю ночь не ем, весь день не сплю — устаю
Re: Целесообразно ли использовать LINQ to SQL для такой зада
От: Mr.Cat  
Дата: 04.08.10 06:46
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Мне надо как-то цеплять join'ы динамически. То есть что-то похожее на:
А>
А>Сделать Linq для выбора Customers. Что-то типа IQueryable<Customer> q = db.Customers.Select(c => c);
А>IF (пользователь чекнул "вместе с продуктами")
А>{
А>  тут добавить join на fn_GetProducts()
А>}
А>IF (пользователь чекнул "вместе с ещё чем-то")
А>{
А>  тут добавить join на fn_GetЕщёЧтото()
А>}
А>и т.д.
А>


Ну дык юзаем обычный join из linq:
var query1 = ... //whatever query
var query2 = from r1 in query
             join r2 in dataContext.some_function() on r1.FIELD equals r2.FIELD
             select new ...;

some_function надо, ессно, в дата контексте замапить на "табличную" функцию. Либо в дизайнере (он умеет — достаточно перетащить функцию из сервер-эксплорера), либо руками, подглядев, как это делает дизайнер.
Re[2]: Целесообразно ли использовать LINQ to SQL для такой з
От: Аноним  
Дата: 04.08.10 08:29
Оценка:
Здравствуйте, Neco, Вы писали:

N>ну where условия так точно можно добавлять. А раз можно их, то почему не всё остальное?

N>Единственное надо определиться с возвращаемым таким методом типом — видимо он должен быть "на все случаи жизни".

Как я писал с where проблем нет, ибо при использовании цепочки where возвращаемые значения все будут одного типа.
С join у меня не получается. В зависимости от того что мы джоиним мы получаем разные типы.
Буду благодарен за пример с несколькими join...
Re[2]: Целесообразно ли использовать LINQ to SQL для такой з
От: Аноним  
Дата: 04.08.10 08:56
Оценка:
Здравствуйте, Mr.Cat, Вы писали:

MC>Ну дык юзаем обычный join из linq:

MC>
MC>var query1 = ... //whatever query
MC>var query2 = from r1 in query
MC>             join r2 in dataContext.some_function() on r1.FIELD equals r2.FIELD
MC>             select new ...;
MC>

MC>some_function надо, ессно, в дата контексте замапить на "табличную" функцию. Либо в дизайнере (он умеет — достаточно перетащить функцию из сервер-эксплорера), либо руками, подглядев, как это делает дизайнер.


У меня не получается добиться нужного мне результата.
Сделать 1 джоин как Вы написали не проблема. Проблема с типами в последующих джоинах.
Рассмотрим мою проблему подробнее:

//Сделать Linq для выбора Customers. Что-то типа 
IQueryable<Customer> q = db.Customers.Select(c => c);  // очевидно что тип переменной q тут IQueryable<Customer>
IF (пользователь чекнул "вместе с продуктами")
{
//  тут добавить join на fn_GetProducts()
  var q2 = from customer in q
        join product in db.fn_GetProducts() on customer.ID equals product.ID
        select new {customer.ID, customer.Name, product.Description};

// тут мне было б неплохо присвоить 
// q = q2; 
// чтоб в последующих if джойнить q на следующие условия. Но это присвоение невозможно, так как типы у q и q2 разные.
// может это неправильно у меня select new {customer.ID, customer.Name, product.Description}; ? А как тогда?
}
IF (пользователь чекнул "вместе с ещё чем-то")
{
// В зависимости от состояния чекбокса "вместе с продуктами" тут мне надо заджойнить либо q либо q2 на fn_GetЕщёЧтото()
}
и т.д.
Re[3]: Целесообразно ли использовать LINQ to SQL для такой з
От: Mr.Cat  
Дата: 04.08.10 10:00
Оценка:
Значит, надо сделать так, чтоб независимо от набора дополнительных джоинов селектом возвращались объекты одного и того же типа.
Re[4]: Целесообразно ли использовать LINQ to SQL для такой з
От: Аноним  
Дата: 04.08.10 10:25
Оценка:
Здравствуйте, Mr.Cat, Вы писали:

MC>Значит, надо сделать так, чтоб независимо от набора дополнительных джоинов селектом возвращались объекты одного и того же типа.


Как??
Джоины мне нужны, чтоб соединять разные таблички. Разные таблички хранят разные сущности, имеют разный набор полей.
Можете привести практический пример? Можно даже просто на LINQ без привязки к SQL.
Re[5]: Целесообразно ли использовать LINQ to SQL для такой з
От: Mr.Cat  
Дата: 04.08.10 18:21
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Как??
А>Джоины мне нужны, чтоб соединять разные таблички. Разные таблички хранят разные сущности, имеют разный набор полей.
А как было раньше? В результате разных комбинаций джойнов получались разные сущности или одна? Linq в этом плане ничего не меняет.
Например, можно попробовать для результата джойна сделать сущность-наследника (относительно запроса без джойна), только надо быть аккуратным, ибо IQueriable не ковариантен (т.е., где надо, попробовать заюзать OfType или Cast).

PS: Самому интересно стало, будет минутка — может, поэкспериментирую.
Re[3]: Целесообразно ли использовать LINQ to SQL для такой з
От: Neco  
Дата: 06.08.10 15:51
Оценка:
Здравствуйте, Аноним, Вы писали:

А>С join у меня не получается. В зависимости от того что мы джоиним мы получаем разные типы.

А>Буду благодарен за пример с несколькими join...

как-то так попробуйте:
    class temp {
        public temp() {
            var q = new List<SrcCustomer>().Select(c => new Data { Customer = c });
            if (1 == 1) {
                q = from customer in q
                    join order in (new List<SrcOrder>()) on customer.Customer.Id equals order.CustomerId
                    group order by customer into all
                    select new Data { Customer = all.Key.Customer, Orders = all, Department = all.Key.Department };
            }
            if (1 == 1) {
                q = from customer in q
                    join dept in (new List<SrcDepartment>()) on customer.Customer.DepartmentId equals dept.Id
                    select new Data { Customer = customer.Customer, Orders = customer.Orders, Department = dept };
            }
        }
        private class SrcCustomer {
            public int Id { get; set; }
            public int DepartmentId { get; set; }
            public string FullName { get; set; }
        }
        private class SrcDepartment {
            public int Id { get; set; }
            public string Name { get; set; }
        }
        private class SrcOrder {
            public int Id { get; set; }
            public int CustomerId { get; set; }
            public string ProductName { get; set; }
        }
        private class Data {
            public SrcCustomer Customer { get; set; }
            public IEnumerable<SrcOrder> Orders { get; set; }
            public SrcDepartment Department { get; set; }
        }
    }

с заказами мог напортачить — не умею я пользоваться группировкой линковской. Но суть не в этом.
всю ночь не ем, весь день не сплю — устаю
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.