QueryOver - 我认为ID是免费的吗?

时间:2011-10-28 21:43:01

标签: nhibernate subquery queryover

我花了一段时间,但我想出了如何得到我想要的东西 - 主要是。 我的代码:

        var sq = QueryOver.Of<VehicleGroup>(() => vehicleGroup)
                    .JoinQueryOver<Manager>(vg => vg.Managers)
                        .Where(man => man.Id == managerId)
                    .JoinQueryOver<TruckPCBase>(() => vehicleGroup.Vehicles)
                        .Where(v => v.Id == item.VehicleId)
                    .Select(vg => vg.Id)
                    ;

        var vp = Session.QueryOver<Summary>(() => item)
            .WithSubquery.WhereExists(sq)
            .Take(10)
            .List();

这正是我想要的。

但是,我必须映射一个额外的字段才能使其正常工作。

Summary对象有一个VehicleBase组件。我想做的是:

        var sq = QueryOver.Of<VehicleGroup>(() => vehicleGroup)
                    .JoinQueryOver<Manager>(vg => vg.Managers)
                        .Where(man => man.Id == managerId)
                    .JoinQueryOver<TruckPCBase>(() => vehicleGroup.Vehicles)
                        .Where(v => v.Id == item.VehicleBase.Id)
                    .Select(vg => vg.Id)
                    ;

        var vp = Session.QueryOver<Summary>(() => item)
            .WithSubquery.WhereExists(sq)
            .Take(10)
            .List();

这会出现以下错误:

System.NullReferenceException: Object reference not set to an instance of an object.
at lambda_method(ExecutionScope ) 

好的,所以我添加了一个额外的提取:

        var sq = QueryOver.Of<VehicleGroup>(() => vehicleGroup)
                    .JoinQueryOver<Manager>(vg => vg.Managers)
                        .Where(man => man.Id == managerId)
                    .JoinQueryOver<TruckPCBase>(() => vehicleGroup.Vehicles)
                        .Where(v => v.Id == item.VehicleBase.Id)
                    .Select(vg => vg.Id)
                    ;

        var vp = Session.QueryOver<Summary>(() => item)
            .Fetch(sum => sum.VehicleBase).Eager
            .WithSubquery.WhereExists(sq)
            .Take(10)
            .List();

没有骰子。我不想在我的Summary类(VehicleId)中添加新属性 - 我想通过Summary.VehicleBase.Id

访问它

建议?

2 个答案:

答案 0 :(得分:0)

我无法完全理解您要尝试做什么,但问题似乎是:

你得到这个例外,因为这行

.Where(v => v.Id == item.VehicleBase.Id)

item为空。 nhibernate的linq表达式计算器将尝试热切地评估不包含lambda参数的所有内容。对于这种情况:

稍后将评估

v.Id =>并转向HQL item.VehicleBase.Id =>不依赖于v,因此评估者会急切地评估它会抛出一个NRE。

答案 1 :(得分:0)

让它工作!!!

var sq = QueryOver.Of<VehicleGroup>()
    .Inner.JoinAlias(vg => vg.Managers, () => manager)
    .Where(() => manager.Id == managerId)
    .JoinQueryOver(x => x.Vehicles, () => vehicle)
    .Select(x => vehicle.Id)
    ;


var vp = Session.QueryOver<Summary>()
    .Fetch(vpr => vpr.VehicleBase).Eager
    .WithSubquery.WhereProperty(x => x.VehicleBase.Id).In(sq)
    .Take(10)
    .List()
    ;

这将生成以下SQL

SELECT
    TOP (@p0) this_.summaryID as summaryID42_1_,
    ... close to 200 columns cut ...
FROM
    dbo.Summary this_ 
left outer join
    dbo.Vehicle vehiclebas2_ 
        on this_.VehicleID = vehiclepcbas2_.VehicleID 
WHERE
    this_.vehicleID in (
        SELECT
            vehicle2_.vehicleID as y0_ 
        FROM
            dbo.Groups this_0_ 
        inner join
            dbo.Manager_Rel managers4_ 
                on this_0_.groupId=managers4_.groupId 
        inner join
            dbo.Managers manager1_ 
                on managers4_.managerId=manager1_.ManagerId 
        inner join
            dbo.Object_Rel vehicles6_ 
                on this_0_.groupId=vehicles6_.groupId 
        inner join
            dbo.Vehicle vehicle2_ 
                on vehicles6_.ID=vehicle2_.VehicleID 
        WHERE
            this_0_.type=1 
            AND manager1_.ManagerId = @p1
    );
@p0 = 10 [Type: Int32 (0)], @p1 = 34 [Type: Int32 (0)]

完全(我认为)我想要的东西。