将SQL过程转换为Linq

时间:2009-11-26 21:10:58

标签: linq

在Sql中,假设我有以下程序

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)))

是否可以将此sql查询转换为Linq?

3 个答案:

答案 0 :(得分: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 - 我不知道,但值得一试。)

答案 1 :(得分:0)

仅仅因为可能并不意味着你应该。使用@variable IS NULL OR @ variable = field(或者更糟糕的是,使用IN运算符)几乎是确保删除性能的可靠方法。

使用显式IF语句并在T-SQL中单独使用SELECT,并在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参数尝试构建满足不同条件的单个SELECT的问题是SQL stil必须构建一个查询计划以涵盖所有可能的组合。大多数情况下,这个计划将是进行全表扫描的最糟糕的计划。即使计划以某种方式进行了优化,它也会针对计划生成时的@variable值进行优化(由于parameter sniffing),并且当@variables具有不同的值时,此计划的执行情况甚至会比平凡计划更糟糕在随后的执行中。

答案 2 :(得分: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();
}