具有JoinAlias的Nhibernate查询版本上的TargetInvocationException异常 产品productAlias=null; 会话sessionAlias=null; slotAlias=null; Price-priceAlias=null; var queryOver=session.queryOver(()=>slotAlias) .JoinAlias(()=>slotAlias.Session,()=>sessionAlias) .JoinAlias(()=>sessionAlias.Product,()=>productAlias); if(productGuid.HasValue) { var productEntity=session.Query().FirstOrDefault(x=>x.Guid==productGuid.Value); queryOver=queryOver.Where(()=>productAlias.Id==productEntity.Id); } 如果(仅可用) { queryOver=queryOver.Where(()=>slotAlias.StartDate>=DateTimeOffset.UtcNow.AddMinutes(productAlias.Duration)); } queryOver.List();

具有JoinAlias的Nhibernate查询版本上的TargetInvocationException异常 产品productAlias=null; 会话sessionAlias=null; slotAlias=null; Price-priceAlias=null; var queryOver=session.queryOver(()=>slotAlias) .JoinAlias(()=>slotAlias.Session,()=>sessionAlias) .JoinAlias(()=>sessionAlias.Product,()=>productAlias); if(productGuid.HasValue) { var productEntity=session.Query().FirstOrDefault(x=>x.Guid==productGuid.Value); queryOver=queryOver.Where(()=>productAlias.Id==productEntity.Id); } 如果(仅可用) { queryOver=queryOver.Where(()=>slotAlias.StartDate>=DateTimeOffset.UtcNow.AddMinutes(productAlias.Duration)); } queryOver.List();,nhibernate,queryover,Nhibernate,Queryover,当我运行此查询时,我会得到TargetInvocationException。在内部消息中,slotAlias.StartDate是一个NullReferenceException(第18行,onlyAvailable if子句中) 像这样在if子句和多个Where子句中使用别名是否有问题 堆栈跟踪: Product productAlias = null; Session sessionAlias = null; Slot slotAlias = null; Price priceAlias

当我运行此查询时,我会得到TargetInvocationException。在内部消息中,slotAlias.StartDate是一个NullReferenceException(第18行,onlyAvailable if子句中)

像这样在if子句和多个Where子句中使用别名是否有问题

堆栈跟踪:

Product productAlias = null;
Session sessionAlias = null;
Slot slotAlias = null;
Price priceAlias = null;

var queryOver = session.QueryOver<Slot>(() => slotAlias)
    .JoinAlias(() => slotAlias.Session, () => sessionAlias)
    .JoinAlias(() => sessionAlias.Product, () => productAlias);

if (productGuid.HasValue)
{
    var productEntity = session.Query<Product>().FirstOrDefault(x => x.Guid == productGuid.Value);
    queryOver = queryOver.Where(() => productAlias.Id == productEntity.Id);
}

if (onlyAvailable)
{
    queryOver = queryOver.Where(() => slotAlias.StartDate >= DateTimeOffset.UtcNow.AddMinutes(productAlias.Duration));
}

queryOver.List();
System.Reflection.TargetInvocationException:调用的目标已引发异常。-->System.NullReferenceException:对象引用未设置为对象的实例。
lambda_法(闭合)
---内部异常堆栈跟踪的结束---
位于System.RuntimeMethodHandle.InvokeMethod(对象目标、对象[]参数、签名符号、布尔构造函数)
位于System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(对象obj,对象[]参数,对象[]参数)
位于System.Delegate.DynamicInvokeImpl(对象[]args)
位于NHibernate.Impl.ExpressionProcessor.FindValue(表达式)
位于NHibernate.Impl.ExpressionProcessor.ProcessSimpleExpression(表达式左、表达式右、表达式类型节点类型)
在NHibernate.Impl.ExpressionProcessor.ProcessSimpleExpression(BinaryExpression be)中
位于NHibernate.Impl.ExpressionProcessor.ProcessBinaryExpression(二进制表达式)
位于NHibernate.Impl.ExpressionProcessor.ProcessExpression(表达式表达式)
at NHibernate.criteria.QueryOver`2.NHibernate.IQueryOver.Where(表达式`1表达式)
在C:\Users\erkin\Desktop\Fullseats\Fullseats\Fullseats.Api\Fullseats.Database\Repositories\Repository.GetSlots(Int32限制,Int32偏移量,可空'1 operatorGuid,可空'1 productGuid,可空'1 from,可空'1 to,仅布尔值可用)中的C:\Users\erkin\Desktop\Fullseats\Fullseats\Fullseats.Api
在C:\Users\erkin\Desktop\Fullseats\Fullseats.Api\Fullseats.Server\Core\Services.ProductService.GetSlots(Guid productGuid,PaginationQuery PaginationQuery)中的Fullseats.Server.Core.Services.ProductService.GetSlots(Guid productGuid,PaginationQuery PaginationQuery):第63行
在C:\Users\erkin\Desktop\Fullseats\Fullseats.Api\Fullseats.Server\Modules\ProductModule.GetSlotsForProduct(对象arg)中的Fullseats.Server.Modules.ProductModule.GetSlotsForProduct(对象arg):第224行
在CallSite.Target(闭包、CallSite、Func`2、对象)
在System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](调用站点,T0 arg0,T1 arg1)
在Nancy.Routing.Route.c__;u DisplayClass4.b__;u 3(对象参数,CancellationToken上下文)
使用此行:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at lambda_method(Closure )
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
   at System.Delegate.DynamicInvokeImpl(Object[] args)
   at NHibernate.Impl.ExpressionProcessor.FindValue(Expression expression)
   at NHibernate.Impl.ExpressionProcessor.ProcessSimpleExpression(Expression left, Expression right, ExpressionType nodeType)
   at NHibernate.Impl.ExpressionProcessor.ProcessSimpleExpression(BinaryExpression be)
   at NHibernate.Impl.ExpressionProcessor.ProcessBinaryExpression(BinaryExpression expression)
   at NHibernate.Impl.ExpressionProcessor.ProcessExpression(Expression expression)
   at NHibernate.Criterion.QueryOver`2.NHibernate.IQueryOver<TRoot,TSubType>.Where(Expression`1 expression)
   at Fullseats.Database.Repositories.Repository.GetSlots(Int32 limit, Int32 offset, Nullable`1 operatorGuid, Nullable`1 productGuid, Nullable`1 from, Nullable`1 to, Boolean onlyAvailable) in C:\Users\erkin\Desktop\FullSeats\Fullseats.Api\Fullseats.Database\Repositories\Repository.cs:line 455
   at Fullseats.Server.Core.Services.ProductService.GetSlots(Guid productGuid, PaginationQuery paginationQuery) in C:\Users\erkin\Desktop\FullSeats\Fullseats.Api\Fullseats.Server\Core\Services\ProductService.cs:line 63
   at Fullseats.Server.Modules.ProductModule.GetSlotsForProduct(Object arg) in C:\Users\erkin\Desktop\FullSeats\Fullseats.Api\Fullseats.Server\Modules\ProductModule.cs:line 224
   at CallSite.Target(Closure , CallSite , Func`2 , Object )
   at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
   at Nancy.Routing.Route.<>c__DisplayClass4.<Wrap>b__3(Object parameters, CancellationToken context)
实际上,您是在混合应用程序端逻辑和数据库端逻辑<在将查询发送到数据库之前执行code>DateTimeOffset.UtcNow.AddMinutes。这就是为什么传递常量值而不是
productAlias.Duration
,有效的原因

由于没有将预定义值作为参数发送,因此需要在数据库中执行日期操作

根据您的方言,执行此操作可能需要几个步骤。我将假设SQL Server 2012

  • 使用定义
    addminutes
    函数的函数创建自定义方言:

    queryOver.Where(
        () => slotAlias.StartDate >= DateTimeOffset.UtcNow.AddMinutes(productAlias.Duration));
    
  • 在查询中使用新注册的函数:

    public class MyDialect : MsSql2012Dialect
    {
        public MyDialect()
        {
            this.RegisterFunction(
                "addminutes",
                new SQLFunctionTemplate(NHibernateUtil.DateTimeOffset, "dateadd(n, ?1, ?2)"));
        }
    }
    
  • 这将生成如下所示的SQL代码段:

    queryOver = queryOver.Where(
        Restrictions.GeProperty(
            Projections.Property(() => slotAlias.StartDate),
            Projections.SqlFunction(
                "addminutes",
                NHibernateUtil.DateTimeOffset,
                Projections.Property(() => productAlias.Duration),
                Projections.Constant(DateTimeOffset.UtcNow))))
    
    C#可能有点难读,您可以重构出
    SqlFunction
    部分:

    WHERE
        slotAlia_1.StartDate >= dateadd(minute, this_.Duration, '8/9/2016 2:22:48 AM +00:00');
    

    您应该能够做到这一点--您可以发布完整的异常文本吗?我想知道它是否与@AndrewHitaker有关。当我使用productAlias.Duration时,问题就发生了。如果我只使用其中的任何数字,它就可以工作了。啊,好的。我滚动得不够远——问题是表达式
    ()=>…
    中的代码被转换为SQL。NHibernate不知道如何处理
    DateTimeOffset.UtcNow.AddMinutes(productAlias.Duration)
    位。我将发布一个完整的答案afternoon@AndrewWhitaker非常感谢。顺便说一句,你的博客的超级粉丝。通读一遍。我认为它可以使用一些现实生活中的例子,虽然复杂的安静:)谢谢你的惊人的答案。不是将时间添加到DateTimeOffset.UtcNow,而是将其添加到slotAlias.StartDate中也不起作用。既然slotAlias.StartDate和productAlias.Duration都是数据库值,那么这不应该起作用吗?slotAlias.StartDate.AddMinutes(productAlias.Duration*-1)>=DateTimeOffset。UtcNow@erkinyldz:不,那也不行,原因类似。基本上,NHibernate不知道如何将
    DateTimeOffset
    上的
    AddMinutes
    方法转换为SQL表达式,因此需要通过提供自定义函数来帮助实现。好的,明白了。谢谢你的帮助。
    var addMinutesFunction = Projections.SqlFunction(
        "addMinutes",
        NHibernateUtil.DateTimeOffset,
        Projections.Property(() => productAlias.Duration),   
        Projections.Constant(DateTimeOffset.UtcNow))
    
    queryOver = queryOver.Where(
        Restrictions.GeProperty(
            Projections.Property(() => slotAlias.StartDate), addMinutesFunction))