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 列表作为该方法的参数。我想通过匹配该车辆类型的 MakeModel 从 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> 我可以使用 AnyAsyncToListAsync 进行查询 async 吗? (我知道我必须使方法与任务异步,并在内部使用 await 但是我无法弄清楚异步查询语法)

这是因为当一个 table 来自 dbContext 而另一个来自内存可枚举时,你不能在 linq 中进行嵌套查询,所以如果 dbcontext.Carsdbcontext.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