Как заставить linq производить именно тот sql, который я хочу? - PullRequest
6 голосов
/ 27 апреля 2009

Для меня это вторая натура - собрать какой-то сложный код обработки набора SQL для решения различных вопросов модели предметной области. Тем не менее, тенденция больше не касается SQL. Существует ли какой-либо шаблон ссылки или инструмент преобразования, который помогает преобразовывать различные шаблоны SQL в синтаксис Linq?

Я бы искал способы кодирования таких вещей, как следующий код: (здесь есть подзапрос):

SELECT * FROM orders X WHERE
(SELECT COUNT(*) FROM orders Y
WHERE Y.totalOrder > X.totalOrder) < 6

(Возьмите пять самых высоких заказов с побочными эффектами)

В качестве альтернативы, откуда вы знаете, что Linq выполняется как один оператор без использования отладчика? Я знаю, что вам нужно следовать перечислению, но я бы предположил, что просто где-то ищите шаблоны.

Это с сайта MSDN, который является их примером изменения SQL. Я, вероятно, ошибаюсь, но я не думаю, что это использует обработку множества на сервере (я думаю, что он тянет оба набора локально, тогда берет разницу, которая была бы очень неэффективна). Я, вероятно, ошибаюсь, и это может быть одним из шаблонов в этой ссылке.

Пример разницы SQL:

var differenceQuery =
(from cust in db.Customers
select cust.Country)
.Except
    (from emp in db.Employees
    select emp.Country);

Спасибо

- Обновление:

- 101 образец Microsoft Linq в C # - более близкое средство построения linq в шаблоне для создания необходимого SQL. Я буду публиковать больше, как я нахожу их. Я действительно ищу методологию (шаблоны или инструмент преобразования) для преобразования SQL в Linq.

- Обновление (sql из разностного паттерна Microsoft в Linq):

SELECT DISTINCT [t0].[field] AS [Field_Name]
FROM [left_table] AS [t0]
WHERE NOT (EXISTS(
SELECT NULL AS [EMPTY]
FROM [right_table] AS [t1]
WHERE [t0].[field] = [t1].[field]
))

Это то, что мы хотели, а не то, что я ожидал. Итак, это один шаблон для запоминания.

Ответы [ 5 ]

7 голосов
/ 27 апреля 2009

Если у вас есть рукописный SQL, вы можете использовать ExecuteQuery, указав тип «строки» в качестве аргумента шаблона функции:

var myList = DataContext.ExecuteQuery<MyRow>(
    "select * from myview");

Класс "row" предоставляет столбцы в качестве открытых свойств. Например:

public class MyRow {
    public int Id { get; set; }
    public string Name { get; set; }
    ....
}

Вы можете украсить столбцы с дополнительной информацией:

public class MyRow {
    ....
    [Column(Storage="NameColumn", DbType="VarChar(50)")]
    public string Name { get; set; }
    ....
}

По моему опыту, linq to sql не генерирует очень хороший код SQL, а код, который он генерирует, разбивается на большие базы данных. Что очень хорошо делает linq to sql - это предоставляет хранимые процедуры вашему клиенту. Например:

var result = DataContext.MyProcedure(a,b,c);

Это позволяет хранить SQL в базе данных, обладая преимуществами простой в использовании автоматически создаваемой оболочки .NET.

Чтобы увидеть точный используемый SQL, вы можете использовать инструмент SQL Server Profiler:

http://msdn.microsoft.com/en-us/library/ms187929.aspx

Визуализатор отладки Linq-to-Sql:

http://weblogs.asp.net/scottgu/archive/2007/07/31/linq-to-sql-debug-visualizer.aspx

Или вы можете написать собственный код для регистрации запросов:

http://goneale.wordpress.com/2008/12/31/log-linq-2-sql-query-execution-to-consoledebug-window/

4 голосов
/ 27 апреля 2009

Вот почему Linq Pad был создан в первую очередь. :) Это позволяет легко увидеть, что на выходе. Каковы будут результаты запроса и т. Д. Лучше всего это бесплатно. Может быть, не ответ на ваш вопрос, но я уверен, что это может помочь вам.

2 голосов
/ 27 апреля 2009

Если вас беспокоит сгенерированный TSQL, я бы предложил формализовать запросы в хранимые процедуры или UDF и обращаться к ним через контекст данных. Подход UDF имеет несколько лучшие метаданные и компоновку (по сравнению с хранимой процедурой) - например, вы можете добавить дополнение Where / Skip / Take и т. Д. К запросу UDF и запустить его в базе данных (но в последний раз проверено, только использование LINQ-to-SQL (не Entity Framework) поддерживает использование UDF).

Вы также можете использовать ExecuteQuery, но у базы данных есть свои фиксированные запросы.

Чтобы узнать, что TSQL выполнил ... с LINQ-to-SQL вы можете назначить любой TextWriter (например, Console.Out) на DataContext.Log.

2 голосов
/ 27 апреля 2009

Если вы точно знаете, какой sql вы хотите, то вам следует использовать ExecuteQuery .

Я могу представить несколько способов перевести запрос, который вы показали, но если вас беспокоит, что "Кроме" может не переводиться.

  1. Проверьте это. Если это работает так, как вы хотите, то отлично, иначе:
  2. Перепишите его с элементами, которые, как вы знаете, переведут, например:

    db.Customers.Where (c =>! Db.Employees.Any (e => c.Country == e.Country));

1 голос
/ 27 апреля 2009

Я считаю, что лучше всего использовать хранимые процедуры. В этом случае вы имеете полный контроль над SQL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...