我有以下查询,当变量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;
其实是看起来像旧错误“空集合的聚合”但我不确定这是不是。而且,它是如何修复的。
答案 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))
也有效。