Linq to SQL 如何编写 "not-in" 查询
Linq to SQL How to write "not-in" query
我有以下 3 tables(每种车辆类型有 1 个基地 table 和其他 2 个卫星 tables。)
车辆
ID VehicleType
-----------------------------
1 Car
2 Truck
汽车
ID Make Model
-------------------------
1 Toyota Camry
2 Honda Accord
卡车
ID Make Model
--------------------
1 Ford F150
2 Dodge Ram
那我有对应的DTO
public class VehicleDTO
{
public int ID {get;set;}
public int VehicleType {get;set;}
public IEnumerable<CarDTO> Cars {get;set;}
public IEnumerable<TruckDTO> Trucks {get;set;}
}
public class CarDTO
{
public int ID {get;set;}
public string Make {get;set;}
public string Model {get;set;}
}
public class TruckDTO
{
public int ID {get;set;}
public string Make {get;set;}
public string Model {get;set;}
}
然后我将 Vehicle DTO 列表作为该方法的参数。我想通过匹配该车辆类型的 Make
和 Model
从 DTO 列表中查找数据库中不存在的车辆。
想法是然后将丢失的车辆插入数据库。
我有以下查询
public void FindMissingVehicles(IEnumerable<VehicleDTO> dtos)
{
var cars = (from dto in dtos
where !(from c in dbcontext.Cars
select new { c.Make, c.Model })
.Any(x => dto.VehicleType == 'Car' && dto.Car.Make == x.Make && dto.Car.Model == x.Model)
select dto).ToList();
var trucs = (from dto in dtos
where !(from t in dbcontext.Trucks
select new { t.Make, t.Model })
.Any(x => dto.VehicleType == 'Truck' && dto.Truck.Make == x.Make && dto.Truck.Model == x.Model)
select dto).ToList();
//insert missing cars and trucks into db here
}
上面的查询抛出异常
Message "Non-static method requires a target." string
问题
1> 我如何构造这个查询。
2> 我可以使用 AnyAsync
和 ToListAsync
进行查询 async
吗? (我知道我必须使方法与任务异步,并在内部使用 await 但是我无法弄清楚异步查询语法)
这是因为当一个 table 来自 dbContext 而另一个来自内存可枚举时,你不能在 linq 中进行嵌套查询,所以如果 dbcontext.Cars
和 dbcontext.Trucks
没有很多行,最好将它们加载到内存中并使用如下嵌套查询:
var listCars = dbcontext.Cars.ToList();
var listTrucks = dbcontext.Trucks.ToList();
var cars = (from dto in dtos
where !(from c in listCars
select new { c.Make, c.Model })
.Any(x => dto.VehicleType == 'Car' && dto.Car.Make == x.Make && dto.Car.Model == x.Model)
select dto).ToList();
var trucs = (from dto in dtos
where !(from t in listTrucks
select new { t.Make, t.Model })
.Any(x => dto.VehicleType == 'Truck' && dto.Truck.Make == x.Make && dto.Truck.Model == x.Model)
select dto).ToList();
此外,您的方法存在性能问题 - 您执行 N 个查询 - 每个 dto
个查询,而不是 只执行两个 查询:一个用于汽车,一个用于卡车:
var allCars = dtos.Where(x => x.VehicleType == "Car").ToList()
.SelectMany(x => x.Cars.Select(y => y.Make + "-" + y.Model).ToList()).ToList();
var existedCars = await dbcontext.Cars.Where(x => allCars.Contains(x.Make + "-" + x.Model))
.Select(x => x.Make + "-" + x.Model).ToListAsync();
var newCars = allCars.Except(existedCars).Select(x =>
{
var temp = x.Split('-');
return new CarDTO
{
Make = temp[0],
Model = temp[1]
};
}).ToList();
//exactly same code for Trucks
我有以下 3 tables(每种车辆类型有 1 个基地 table 和其他 2 个卫星 tables。)
车辆
ID VehicleType
-----------------------------
1 Car
2 Truck
汽车
ID Make Model
-------------------------
1 Toyota Camry
2 Honda Accord
卡车
ID Make Model
--------------------
1 Ford F150
2 Dodge Ram
那我有对应的DTO
public class VehicleDTO
{
public int ID {get;set;}
public int VehicleType {get;set;}
public IEnumerable<CarDTO> Cars {get;set;}
public IEnumerable<TruckDTO> Trucks {get;set;}
}
public class CarDTO
{
public int ID {get;set;}
public string Make {get;set;}
public string Model {get;set;}
}
public class TruckDTO
{
public int ID {get;set;}
public string Make {get;set;}
public string Model {get;set;}
}
然后我将 Vehicle DTO 列表作为该方法的参数。我想通过匹配该车辆类型的 Make
和 Model
从 DTO 列表中查找数据库中不存在的车辆。
想法是然后将丢失的车辆插入数据库。
我有以下查询
public void FindMissingVehicles(IEnumerable<VehicleDTO> dtos)
{
var cars = (from dto in dtos
where !(from c in dbcontext.Cars
select new { c.Make, c.Model })
.Any(x => dto.VehicleType == 'Car' && dto.Car.Make == x.Make && dto.Car.Model == x.Model)
select dto).ToList();
var trucs = (from dto in dtos
where !(from t in dbcontext.Trucks
select new { t.Make, t.Model })
.Any(x => dto.VehicleType == 'Truck' && dto.Truck.Make == x.Make && dto.Truck.Model == x.Model)
select dto).ToList();
//insert missing cars and trucks into db here
}
上面的查询抛出异常
Message "Non-static method requires a target." string
问题
1> 我如何构造这个查询。
2> 我可以使用 AnyAsync
和 ToListAsync
进行查询 async
吗? (我知道我必须使方法与任务异步,并在内部使用 await 但是我无法弄清楚异步查询语法)
这是因为当一个 table 来自 dbContext 而另一个来自内存可枚举时,你不能在 linq 中进行嵌套查询,所以如果 dbcontext.Cars
和 dbcontext.Trucks
没有很多行,最好将它们加载到内存中并使用如下嵌套查询:
var listCars = dbcontext.Cars.ToList();
var listTrucks = dbcontext.Trucks.ToList();
var cars = (from dto in dtos
where !(from c in listCars
select new { c.Make, c.Model })
.Any(x => dto.VehicleType == 'Car' && dto.Car.Make == x.Make && dto.Car.Model == x.Model)
select dto).ToList();
var trucs = (from dto in dtos
where !(from t in listTrucks
select new { t.Make, t.Model })
.Any(x => dto.VehicleType == 'Truck' && dto.Truck.Make == x.Make && dto.Truck.Model == x.Model)
select dto).ToList();
此外,您的方法存在性能问题 - 您执行 N 个查询 - 每个 dto
个查询,而不是 只执行两个 查询:一个用于汽车,一个用于卡车:
var allCars = dtos.Where(x => x.VehicleType == "Car").ToList()
.SelectMany(x => x.Cars.Select(y => y.Make + "-" + y.Model).ToList()).ToList();
var existedCars = await dbcontext.Cars.Where(x => allCars.Contains(x.Make + "-" + x.Model))
.Select(x => x.Make + "-" + x.Model).ToListAsync();
var newCars = allCars.Except(existedCars).Select(x =>
{
var temp = x.Split('-');
return new CarDTO
{
Make = temp[0],
Model = temp[1]
};
}).ToList();
//exactly same code for Trucks