当参数为null时查询失败

时间:2013-12-19 13:38:35

标签: c# .net nhibernate linq-to-nhibernate

我有以下查询,当变量regionId如果不为空(它是Nullabel<int>)时工作正常但是当它作为空传递时失败并出现"Object reference not set to an instance of an object"错误。

var result = Session.QueryOver<DtaMonthFreeze>()
    .Where(Restrictions.Eq(Projections.SqlFunction("MONTH", NHibernateUtil.DateTime, Projections.Property<DtaMonthFreeze>(x => x.Date)), monthDate.Month))
    .And(Restrictions.Eq(Projections.SqlFunction("YEAR", NHibernateUtil.DateTime, Projections.Property<DtaMonthFreeze>(x => x.Date)), monthDate.Year))
    .And(x => x.BranchGroupId == regionId || (regionId == null && x.BranchGroupId == null))
    .And(x => x.IsFrozen)
    .List();

这是实体,很简单:

public class DtaMonthFreeze : BaseEntity {
    public virtual Date Date { get; set; }
    public virtual bool IsFrozen { get; set; }
    public virtual int? BranchGroupId { get; set; }
}

相应的映射:

public class DtaMonthFreezeMap : ClassMap<DtaMonthFreeze> {
    public DtaMonthFreezeMap() {
        Table("tbl_dta_month_freeze");
        Id(x => x.Id, "month_freeze_id").GeneratedBy.Identity();
        Map(x => x.Date, "date").Not.Nullable();
        Map(x => x.IsFrozen, "is_frozen").Not.Nullable();
        Map(x => x.BranchGroupId, "branch_group_id").Nullable();
     }
}

经过小规模的研究,我发现如果我更换它:

.And(x => x.BranchGroupId == regionId || (regionId == null && x.BranchGroupId == null))

与此:

.And(x => x.BranchGroupId == regionId || (regionId == null))

错误消失但查询工作不正确。 NHibernate生成的SQL看起来很好(它是前一个调用的代码,其中regionId不为null,因为如果我传递null,那么SQL profiler中不会出现任何内容,所以似乎在NHibernate内部出现错误):

SELECT
    this_.month_freeze_id as month1_11_0_,
    this_.date as date11_0_,
    this_.is_frozen as is3_11_0_,
    this_.branch_group_id as branch4_11_0_
FROM
    dbo.tbl_dta_month_freeze this_
WHERE
    datepart(month, this_.date) = @p0
    and datepart(year, this_.date) = @p1
    and (
        this_.branch_group_id = @p2
        or (
            @p3 is null
            and this_.branch_group_id is null
        )
    )
    and this_.is_frozen = @p4;

其实是看起来像旧错误“空集合的聚合”但我不确定这是不是。而且,它是如何修复的。

2 个答案:

答案 0 :(得分:1)

正如@jbl推荐的那样,我用以下内容替换了我的查询,现在它正在运行。但我仍然不知道为什么我的代码失败了。

    var criteria = Session.CreateCriteria<DtaMonthFreeze>()
        .Add(regionId.HasValue ? Restrictions.Eq("BranchGroupId", regionId) : Restrictions.IsNull("BranchGroupId"))
        .Add(Restrictions.Eq(Projections.SqlFunction("MONTH", NHibernateUtil.DateTime, Projections.Property<DtaMonthFreeze>(x => x.Date)), monthDate.Month))
        .Add(Restrictions.Eq(Projections.SqlFunction("YEAR", NHibernateUtil.DateTime, Projections.Property<DtaMonthFreeze>(x => x.Date)), monthDate.Year))
        .Add(Restrictions.Eq("IsFrozen", true));

    var result = criteria.List<DtaMonthFreeze>();

    return result.Any();

另一个缺点是,我无法查看此代码而不是用血来哭泣。

答案 1 :(得分:0)

您可以尝试以下代码,NH可以正确翻译这些表达式(为简单起见,请将日期部分省略)

int? regionId=1;
bool regionIdIsNull = !regionId.HasValue;

var result = Session.QueryOver<DtaMonthFreeze>()
    .Where(Restrictions.Disjunction()
        .Add<DtaMonthFreeze>(x => regionIdIsNull==true && x.BranchGroupId == null)
        .Add<DtaMonthFreeze>(x => x.BranchGroupId == (regionId.HasValue?regionId:null))
    )
    .And(x => x.IsFrozen)
    .List();

编辑刚刚测试了简单:

.And(x => x.BranchGroupId == (regionId.HasValue ? regionId : null) 
    || (regionIdIsNull == true && x.BranchGroupId == null))

也有效。