2016-08-07 3 views
1
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(); 

このクエリを実行すると、TargetInvocationExceptionが発生します。内部メッセージでは、slotAlias.StartDate(Line 18、onlyAvailable if節内)のNullReferenceExceptionです。TargetInvocationExceptionがJoinAliasのNhibernate QueryOverの場合

if節とこのような複数のWhere節でエイリアスを使用すると何か問題はありますか?

のStackTrace:この行では

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) 
+0

あなたはthis--を行うことができる必要がありますが、完全な例外テキストを投稿することができますか? –

+0

[this JIRA issue](https://nhibernate.jira.com/browse/NH-3822)に関連しているのでしょうか –

+0

@AndrewWhitaker productAlias.Durationを使用すると問題が発生します。私はちょうどそこに任意の番号を使用する場合は動作します。 – erkinyldz

答えて

1

queryOver.Where(
    () => slotAlias.StartDate >= DateTimeOffset.UtcNow.AddMinutes(productAlias.Duration)); 

あなたは、基本的にデータベース側のロジックをアプリケーション側のロジックを混合しています。 DateTimeOffset.UtcNow.AddMinutesの前に実行され、の前にクエリがデータベースに送信されます。だからこそ、一定の値を渡すが、productAlias.Durationではない。

パラメータとして事前定義された値を送信していないので、データベースで日付操作を実行する必要があります。

これを行うには、方言に応じていくつかの手順が必要になることがあります。

:あなたのクエリで新しく登録された関数を使用し

public class MyDialect : MsSql2012Dialect 
{ 
    public MyDialect() 
    { 
     this.RegisterFunction(
      "addminutes", 
      new SQLFunctionTemplate(NHibernateUtil.DateTimeOffset, "dateadd(n, ?1, ?2)")); 
    } 
} 
  • :私はaddminutes機能を定義する機能を持つカスタムの方言を作成してSQL Serverのに2012

    1. を前提とするつもりです

      queryOver = queryOver.Where(
          Restrictions.GeProperty(
           Projections.Property(() => slotAlias.StartDate), 
           Projections.SqlFunction(
            "addminutes", 
            NHibernateUtil.DateTimeOffset, 
            Projections.Property(() => productAlias.Duration), 
            Projections.Constant(DateTimeOffset.UtcNow)))) 
      

    これは、次のようなSQLスニペットを生成します。

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

    C#が、あなたがSqlFunction一部をリファクタリングでき、読み少し難しいことができます:

    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)) 
    
  • +0

    素晴らしい答えをありがとう。 DateTimeOffset.UtcNowに時間を追加するのではなく、それをslotAlias.StartDateに追加することもできませんでした。 slotAlias.StartDateとproductAlias.Durationの両方がデータベース値であるため、それは機能しませんか? slotAlias.StartDate.AddMinutes(productAlias.Duration * -1)> = DateTimeOffset.UtcNow – erkinyldz

    +0

    @erkinyldz:いいえ、同様の理由で、どちらも動作しません。基本的に、NHibernateは、 'DateTimeOffset'の' AddMinutes'メソッドをSQL式に変換する方法を知らないので、カスタム関数を提供することによってそれを助ける必要があります。 –

    +0

    わかりました。お手伝いありがとう。 – erkinyldz

    関連する問題