在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?
答案 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();
}