В предыдущем вопросе я спросил, являются ли библиотеки ORM неоптимальными решениями и получил много хороших отзывов. Как я уже думал об этой проблеме, я пришел к выводу, что основное преимущество LinqToSQL (сейчас) и обещание LinqToEntities (в будущем) заключается в их способности уменьшить «несоответствие» между процедурным кодом и SQL. Учитывая ограничения LinqToSQL как полноценного языка запросов данных, я не склонен соглашаться с тем, что его преимущества выходят далеко за рамки этого, но я хотел бы узнать мнение других.
Для начала, что я подразумеваю под "несоответствием" между процедурным кодом и SQL? Если вы когда-либо разрабатывали приложение для базы данных, то вы, вероятно, уже знакомы (и устали от) шагов, необходимых для взаимодействия с базой данных: установите все параметры, введите команду SQL, а затем вручную преобразуйте ожидаемые результаты обратно в переменные или экземпляры, используемые в коде.
LinqToSql значительно облегчает эту задачу за счет использования «беглых» интерфейсов, лямбда-выражений, методов расширения и т. Д. Конечный результат заключается в том, что легко вставлять собственные скалярные типы C # в вызов поиска данных и автоматически генерировать собственные Экземпляры класса C # Возьмите этот пример с веб-сайта MS:
var q =
from c in db.Customers
where c.City == "London"
select c;
foreach (var cust in q)
Console.WriteLine("id = {0}, City = {1}",cust.CustomerID, cust.City);
Очень круто!
Так в чем же проблема?
Что ж, как я указывал в статье, на которую сверху ссылается, есть ряд проблем. Самый большой showtopper для меня заключался в том, что любой, кто минимально компетентен в SQL, немедленно преодолеет контрольно-пропускные пункты. Дело не только в том, что многие конструкции, созданные в качестве альтернатив SQL, незнакомы или даже неуклюжи (Group By? Мы говорим Ugly в LinqToSql). Большая проблема заключается в том, что существует ряд распространенных конструкций, которые просто не поддерживаются изначально (например, DateDiff). В лучшем случае вы можете «выйти» из Linq и отправить код SQL в поток вызовов Linq.
Итак, не лучше ли просто встраивать SQL в C # (или VB) таким образом, чтобы вы могли свободно указывать свой SQL, но также обеспечивали простое встраивание параметров и автоматическое преобразование в собственные классы? Например, если мы реализуем только шесть функций в одном классе, мы можем написать что-то вроде этого (где qry является экземпляром нашего класса запросов):
var ListOfEnrollees =
qry.Command("Select b.FirstName, b.LastName, b.ID From ClassEnroll a inner join Folder b on (a.ClientID = b.ClientID) ")
.Where ("a.ClassID", classID)
.AND()
.Append("(DateDiff(d, a.ClassDate, @ClassDate) = 0) Order By LastName;")
.ParamVal(classDate)
.ReturnList<EnrollListMemberData>();
Команда просто начинает с сбора оператора SQL, Где запускает наше предложение SQL Where и вводит первый параметр, Append указывает на дополнительный SQL , ParamVal просто вводит значение параметра, соответствующее параметру SQL, найденному в предыдущей строке, а ReturnList делает магию, необходимую для преобразования в класс. Обратите внимание, что это просто SQL: объединения тривиальны, DateDiff (или любая другая конструкция SQL) поддерживается и т. Д. Мы можем проверить это в окне SQL, а затем просто вырезать и вставить в наш код, разбив его соответствующим образом для ввода наши параметры. Это не может быть проще.
Теперь, базовая конструкция, показанная выше, мне кажется невероятно простой, и она может обрабатывать ЛЮБУЮ конструкцию SQL, используя знания SQL, которые у меня уже есть . Мне пришлось использовать некоторое отражение и некоторые другие классные новые конструкции C # 3, чтобы заставить вызовы ReturnList (и аналогичные) работать, но в целом это было довольно просто. Я также добавил несколько наворотов, чтобы сделать интерфейс более плавным. Итак, вот мой вопрос, и где я хотел бы услышать комментарии от сообщества:
Зачем мне когда-либо овладевать тонкостями LinqToEntities или даже нести накладные расходы на LinqToSql? Разве это не дает мне все, что дает мне LinqToSql, и даже больше? Разве он не охватывает даже LinqToEntities, за исключением экзотических отображений реляционных объектов?
Обновление : Хэмиш Смит ниже утверждает, что LINQ может когда-нибудь стать полностью мощным языком манипулирования данными, настолько мощным, что SQL даже не понадобится. Это важный переломный момент, который я не обсуждал, но с которым согласен. Суть моей позиции заключается в том, что, хотя у LinqToSql есть некоторые практические преимущества, он все равно отстает на 1047 * далеко от цели Хэмиша. Это очень реальный и существенный недостаток.
Хэмиш также правильно утверждает, что я все еще работаю со встроенным SQL - я не "решил" проблему. Для меня, однако, это функция , а не ошибка. SQL по-прежнему намного лучше выбирает реляционные данные и манипулирует ими (а это, в конце концов, то, с чем мы работаем), что я хочу, чтобы мог использовать его для разработки моего решения. Я утверждаю, что встроенный SQL - это не проблема, а несоответствие импеданса между ним и C #. Тем не менее, используя новые вдохновленные Linq функции C # 3, я могу в значительной степени устранить это «несоответствие импеданса» и получить лучшее из обоих миров.