2009-11-26 2 views
0

В Sql, скажем, у меня есть следующая процедурапроцедура Преобразование SQL в Linq

GetCars 
(
    @Ids nvarchar(MAX) = NULL  // represent a list of Id (with comma) 
    @TypeIds nvarchar(MAX) = NULL // represent a list of TypeId (with comma) 
) 

// After transforming my Ids and TypeIds into CSVTABLE (comma seperated values table) 

SELECT * FROM CARS 
WHERE ((@Id IS NULL) OR (CARS.Id IN (SELECT Id FROM CSVTABLE)) AND 
     ((@TypeId IS NULL) OR (CARS.TypeId IN (SELECT ID FROM CSVTABLE))) 

Is можно превратить этот SQL запросов в Linq?

+0

BTW ваш ИНЕКЕ не имеют каких-либо условий на автомобили, вы либо собираетесь выбрать все или никто. Вы уверены, что не '(@ID NULL) ИЛИ (Cars.ID IN (SELECT ...))'? –

ответ

0

Я нашел решение.

, что будет что-то вроде этого:

List<Car> Find(List<int> carIds, List<int> carTypeIds) 
{ 
    var carQuery = from c in ctx.Cars 
        select c; 

    if(carIds!=null && carIds.Count>0) 
     carQuery = carQuery.Where(c=> carIds.Contains(c.id)); 


    if(carTypeIds!=null && carTypeIds.Count>0) 
     carQuery = carQuery.Where(c=> carTypeIds.Contains(c.typeId)); 

    return carQuery.ToList(); 
} 
+0

Я думал, вы сказали, что Содержит не поддерживается? –

+0

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

+0

вот ссылка на содержащиеся в EF: http://social.msdn.microsoft.com/forums/en-US/adodotnetentityframework/thread/095745fe-dcf0-4142-b684-b7e4a1ab59f0/ – pdiddy

1

Ну, прямой перевод довольно легко:

var query = from car in dataContext.Cars 
    where car.Id == null || dataContext.CsvTable.Select(x => x.Id) 
               .Contains(car.Id) 
    where car.TypeId == null || dataContext.CsvTable.Select(x => x.TypeId) 
                .Contains(car.TypeId) 
    select car; 

Вы должны попробовать его, чтобы увидеть, если это на самом деле создает правильный SQL, хотя.

Вы можете упростить несколько:

var csvIds = dataContext.CsvTable.Select(x => x.Id); 
var query = from car in dataContext.Cars 
      where car.Id == null || csvIds.Contains(car.Id) 
      where car.TypeId == null || csvIds.Contains(car.TypeId) 
      select car; 

(. Это может производить различные SQL - я не знаю, но это стоит попробовать)

+0

Я думаю, вы имеете в виду «|| csvIds.Contains (car.TypeId)» для второго. –

+0

У меня нет реального CSVTable в моем коде C#. Все, что у меня есть, это список int. Также я использую Entity-Framework, и я думаю, что нет поддержки для содержит ... – pdiddy

+0

Также я не проверяю Car.Id == null .... Меня интересует ли мой список null или нет .... – pdiddy

0

Просто потому, что это возможно, не означает, что вы должен. Использование @variable IS NULL OR @ variable = field (или, что еще хуже, с использованием оператора IN) - это в значительной степени верный способ снижения производительности.

Использование явного IF заявления и отдельные ВЫБИРАЕТ в T-SQL, и приравненных отдельных выражений запросов в LINQ:

IF (@ID IS NULL and @TypeID IS NO NULL) 
    SELECT ... FROM CARS WHERE ... 
ELSE IF (@ID IS NOT NULL AND @TypeID IS NULL) 
    SELECT ... FROM CARS WHERE ... 
ELSE IF (@ID IS NOT NULL AND @TypeID IS NOT NULL) 
SELECT ... 

Проблема с попыткой построить одну единственную ВЫБРАТЬ, который удовлетворяет различным условиям в зависимости от @variable параметров что SQL stil должен построить один запрос план покрытия все возможно комбинация. В большинстве случаев этот план будет самым худшим планом, который выполняет полное сканирование таблицы. Даже когда план каким-то образом оптимизирован, он будет оптимизирован для значений @variable на момент создания плана (из-за parameter sniffing), и этот план будет работать даже хуже, чем тривиальный план, когда @variables имеют разные значения при последующем выполнении.

+0

спасибо, я не специалист по sql, но я понимаю вашу точку зрения. Я просто когда-нибудь думаю, что построение всей комбинации возможностей - особенно, когда у вас может быть много параметров .... – pdiddy

Смежные вопросы