如何在Linq中执行嵌套查询

时间:2012-10-22 13:31:36

标签: c# sql linq entity-framework linq-to-sql

我在C#中有这种格式的LINQ类:

class Vehicle
{
  int _VehicleID
  int _ModelID

  EntetySet<Cars> _AllCars
  EntetySet<Bus> _AllBus
  EntetyRef<Driver> _Person
}

汽车表

CarsID | Manufacturer | Type
1000   | Honda        | Diesel
1001   | Mitsubishi   | Petrol
1002   | Maruti       | Diesel

总线表

BusID | Manufacturer | Type
2000  | Volvo        | Diesel
2001  | TATA         | Petrol
2002  | layland      | Petrol

从UI中,我将获得一个车辆ID作为参数。基于此,所有汽车,总线及其相关表将被复制到变量。那就是:

Vehicle v1 = new Vehicle();
v1 = dc.vehicle.where(v => v.vehicleID == param.vehicleID).findfirst();

我的v1包含满足上述条件的所有表及其内容。

现在,我想根据表格汽车和公共汽车中的表格内容过滤更多内容;即基于车用汽油或柴油的类型。

如果我想在一行中使用查询语句复制所有汽油车和公共汽车,请告诉我。

提前致谢。

2 个答案:

答案 0 :(得分:2)

**根据评论编辑**

你的问题的逻辑在某种程度上被我忽略了,因为我在车辆上采取了合乎逻辑的人性化方法。每当我看到Vehicle class时,我立即将汽车和公共汽车视为车辆。 这更多地表明命名选择不当。 但不再是我的判断。

我知道你想要一辆id的车辆,你希望结果只包含乘坐汽车和公共汽车,就像汽油一样。 如果它被转换为SQL而不是我不知道树可以在选择范围内走多远,但如果它在内存中,那么你可以在子选择中走很长的路。

您可以使用“模型”类来实现这一目标,或者您可以使用匿名类型,但我将为“模型”类提供示例:

示例:

public class VehicleModel
{
    public int VehicleID { get; set; }
    public int ModelID { get; set; }
    public List<Cars> Cars { get; set; }
    public List<Bus> Buses { get; set; }
}

var vehicleID = 1; // just for the example of course.
var fuelType = "Petrol";
var vehicle = (from v in dc.vehicle 
               where v._VehicleID == vehicleID
               select new VehicleModel
               {
                   VehicleID = v._VehicleID,
                   ModelID = v._ModelID,
                   Cars = v._AllCars.Where(car => car.Type == fuelType).ToList(),
                   Buses = v._AllBus.Where(bus => bus.Type == fuelType).ToList()
               }).SingleOrDefault();
               // use FirstOrDefault() when _VehicleID is NOT unique to get TOP 1

不要修改实体本身内的EntitySets,总是使用模型来处理这些事情,因为如果你这样做并在你的EntityContainer上调用保存更改,那么各种各样的事情都可能出错。

如果您想了解匿名类型,请查看此处: http://msdn.microsoft.com/en-us/library/bb397696(v=vs.100).aspx

另请参阅Linq示例: http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b




- 编辑前

你的意思是:

var query = dc.vehicle.Where(v => 
                             v._AllCars.Any(c => c.Manufacturer == "Honda") ||
                             v._AllBuss.Any(b => b.Manufacturer == "Volvo"));

这将为您提供所有车辆本田或公共汽车是沃尔沃的车辆。 这将是:

1000 |本田|柴油
2000年|沃尔沃|柴油

结果是包含满足条件的所有或没有项目的IEnumerable。

如果你只想要第一次点击,你可以这样做:

//if it must exist, otherwise this throws an exception
var firstVehicle = query.First();
//if it may exist, otherwise null
var firstVehicle = query.FirstOrDefault();

答案 1 :(得分:1)

似乎你想要这样的东西:

var v1 = dc.vehicle.Where(v => v.vehicleID == param.vehicleID
                            && v.Cars.All(c => c.Type == "Petrol")
                            && v.Buses.All(c => c.Type == "Petrol")).First();

获得所有汽车和公共汽车都有汽油的“车辆”。 (请注意,我使用的是“汽车”,而不是非常规名称“_AllCars”等。)

修改

或者:

var v1 = dc.vehicle.Where(v => v.vehicleID == param.vehicleID)
    .Select(v => new {
                        Id = v.vehicleID,
                        Cars = v.Cars.Where(c => c.Type == "Petrol"),
                        Buses = v.Buses.Where(c => c.Type == "Petrol")
                     }).First();

获取带有过滤集合的匿名类型。