【问题标题】:Linq to SQL How to write "not-in" queryLinq to SQL 如何编写“不在”查询
【发布时间】:2018-06-22 20:28:20
【问题描述】:

我有以下 3 个表(每种车辆类型有 1 个基本表和其他 2 个卫星表。)

车辆

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;}  
}

然后我将车辆 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

}

上面的查询抛出异常

消息“非静态方法需要一个目标。”字符串

问题

1> 我如何构造这个查询。

2> 我可以使用AnyAsync 和ToListAsync 来查询async。 (我知道我必须使方法与 Task 异步,并在内部使用 await,但是我无法弄清楚异步查询语法)

【问题讨论】:

    标签: entity-framework linq linq-to-sql linq-to-entities


    【解决方案1】:

    此外,您的方法存在性能问题 - 您执行 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
    

    【讨论】:

      【解决方案2】:

      这是因为当一个表来自 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();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-04
        • 1970-01-01
        相关资源
        最近更新 更多