简体   繁体   中英

Nhibernate QueryOver join on multiple columns

I am trying to reproduce this SQL query in NH:

select vehicle.Id, price.Price
from vhc.Vehicle vehicle
    left outer join vhc.VehiclePrice price on vehicle.Id = price.VehicleId 
          and price.VehiclePriceTypeId = 1

where price.Id is null or price.VehiclePriceTypeId = 1
order by price.Price

The important part is the second join criteria. I want to see all Vehicles, regardless of whether they have a price, but if they have any prices, I want to select the price of type 1. Removing that second join criteria means that it excludes all vehicles that only have prices of types 2, 3, etc. That's not ok.

Approaches I've tried:

  • Adding a global filter on the VehiclePrice object to filter only on VehiclePriceType = 1 but it puts it on the Where, not on the Join, so no luck there.

  • Adding a SubQuery for prices with type 1, but, again, it applies it on the Where, not on the Join.

  • Other join types -- Full, Right... don't seem to make sense here.

It's a common problem, just haven't found the solution yet. Any thoughts?

This is now possible with QueryOver (I don't know as of when, however I tried to do this before and could not do so).

var vpAlias = null;
var prices = session.QueryOver<Vehicle>()
    .Left.JoinAlias<VehiclePrice>(x => x.VehiclePrice, () => vpAlias, x => x.VehiclePriceTypeId == 1)
    .Where(() => vpAlias.Id == null || vpAlias.VehiclePriceTypeId == 1)
    .Select(x => x.Id, () => vpAlias.Price)
    .ToList();

You will need to create an alias for the entity on which you would like to join on multiple fields, however it seems you can do so with either JoinAlias or JoinQueryOver , they just return different entities.

just an idea: use 2 Queries in one roundtrip

var vehiclesWithPrice = session.QueryOver<Vehicle>()
    .JoinQueryOver<VehiclePrice>(vehicle => vehicle.Prices, () => vpricealias)
    .Where(price => price.VehiclePriceTypeId == 1)
    .OrderBy(() => vpricealias.Price).Asc
    .Select(vehicle => vehicle.Id, vehicle => vpricealias.Price)
    .Future();

var vehiclesWithoutPrice = session.QueryOver(() => vehiclealias)
    .WithSubquery.WhereNotExists(QueryOver.Of<VehiclePrice>()
        .Where(price => price.Vehicle.Id == vehiclealias.Id)
        .Where(price => price.VehiclePriceTypeId == 1)
    )
    .Select(vehicle => vehicle.Id, vehicle => 0)
    .Future();

var vehiclesprices = vehiclesWithoutPrice.Concat(vehiclesWithPrice);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM