LinqToNhibernate中的DateTime陷阱
能用LinqToNhibernate还是很爽的~~能获得编译时类型检查就不说了,就连where子句的复用都比用HQL爽快很多~~~
比如我有这种有时间限制的实体
public interface ITerminableEntity
{
DateTime StartDate { get; }
DateTime? EndDate { get; }
}
{
DateTime StartDate { get; }
DateTime? EndDate { get; }
}
然后我给实现这种接口的实体统一实现时间判断的where子句
代码
public static class TerminableEntityDAOImpl
{
public static Expression<Func<TEntity, bool>> DateAvailable<TEntity>(this CommonDAOImpl<TEntity> dao, DateTime dt)
where TEntity : ITerminableEntity, IEntity
{
return entity => dt >= entity.StartDate && (!entity.EndDate.HasValue || entity.EndDate.Value > dt);
}
}
{
public static Expression<Func<TEntity, bool>> DateAvailable<TEntity>(this CommonDAOImpl<TEntity> dao, DateTime dt)
where TEntity : ITerminableEntity, IEntity
{
return entity => dt >= entity.StartDate && (!entity.EndDate.HasValue || entity.EndDate.Value > dt);
}
}
使用起来也是简单方便
代码
public IQueryable<ProgramEntity> FindAllByCentre(string entityName, Guid centreId)
{
return FindByCentreId(entityName, centreId).Where(this.DateAvailable(DateTime.Now));
}
{
return FindByCentreId(entityName, centreId).Where(this.DateAvailable(DateTime.Now));
}
一运行却报错!NHibernate.QueryException: could not resolve property: Value
我确信我的实体类和mapping中都没有Value这个字段啊~~~问题肯定出在entity.EndDate.Value > dt这句上,把.Value去掉(亏得.net允许可空类型和非可空类型的比较),果然不报错了,但是显示结果却是空的,啥都没有!
看看生成出的SQL语句
代码
SELECT ... FROM tblMFSServices this_ left outer join tblCentres centre1_ on this_.uidCentreKey=centre1_.uidCentreKey WHERE centre1_.uidCentreKey = @p0 and (this_.dteEffectiveDate <= @p1 and (not (1=1) or this_.dteCeasedDate > @p2))
not (1=1) or this_.dteCeasedDate > @p2)。。。这啥玩意啊。。。真是雷死我了。。。
再改!entity.EndDate == null || entity.EndDate > dt(这次又亏得.net允许可空类型和null比,要是放以前还在使用Nhibernate.Nullables的时代真不知道咋整= =)
这次终于得到了正常的sql语句,显示结果也正常了。
顺便说一句Google这个问题的途中发现老外对LinqToNhibernate中的DateTime真是怨声载道啊,比如你想where someEntity.SomeDateTimeProperty.Date = new Date(2012, 12, 21)就不行~~LinqToNhibernate看来还有待完善啊~~