@@ -228,52 +228,42 @@ async Task<IList> FindAsync(string query, object[] values, IType[] types, Cancel
228228 }
229229 }
230230
231- public override async Task ListAsync ( IQueryExpression queryExpression , QueryParameters queryParameters , IList results , CancellationToken cancellationToken )
231+ public override Task ListAsync ( IQueryExpression queryExpression , QueryParameters queryParameters , IList results , CancellationToken cancellationToken )
232232 {
233- cancellationToken . ThrowIfCancellationRequested ( ) ;
234- using ( new SessionIdLoggingContext ( SessionId ) )
233+ if ( cancellationToken . IsCancellationRequested )
235234 {
236- CheckAndUpdateSessionStatus ( ) ;
237- queryParameters . ValidateParameters ( ) ;
238- var plan = GetHQLQueryPlan ( queryExpression , false ) ;
239-
240- await ( AutoFlushIfRequiredAsync ( plan . QuerySpaces , cancellationToken ) ) . ConfigureAwait ( false ) ;
235+ return Task . FromCanceled < object > ( cancellationToken ) ;
236+ }
237+ return ListAsync ( queryExpression , queryParameters , results , null , cancellationToken ) ;
238+ }
241239
242- bool success = false ;
243- using ( SuspendAutoFlush ( ) ) //stops flush being called multiple times if this method is recursively called
244- {
245- try
246- {
247- await ( plan . PerformListAsync ( queryParameters , this , results , cancellationToken ) ) . ConfigureAwait ( false ) ;
248- success = true ;
249- }
250- catch ( HibernateException )
251- {
252- // Do not call Convert on HibernateExceptions
253- throw ;
254- }
255- catch ( Exception e )
256- {
257- throw Convert ( e , "Could not execute query" ) ;
258- }
259- finally
260- {
261- await ( AfterOperationAsync ( success , cancellationToken ) ) . ConfigureAwait ( false ) ;
262- }
263- }
240+ protected override Task ListFilterAsync ( object collection , IQueryExpression queryExpression , QueryParameters queryParameters , IList results , CancellationToken cancellationToken )
241+ {
242+ if ( collection == null )
243+ throw new ArgumentNullException ( nameof ( collection ) ) ;
244+ if ( cancellationToken . IsCancellationRequested )
245+ {
246+ return Task . FromCanceled < object > ( cancellationToken ) ;
264247 }
248+ return ListAsync ( queryExpression , queryParameters , results , collection , cancellationToken ) ;
265249 }
266250
267- protected override async Task ListFilterAsync ( object collection , IQueryExpression queryExpression , QueryParameters queryParameters , IList results , CancellationToken cancellationToken )
251+ private async Task ListAsync ( IQueryExpression queryExpression , QueryParameters queryParameters , IList results , object filterConnection , CancellationToken cancellationToken )
268252 {
269253 cancellationToken . ThrowIfCancellationRequested ( ) ;
270254 using ( new SessionIdLoggingContext ( SessionId ) )
271255 {
272256 CheckAndUpdateSessionStatus ( ) ;
273257 queryParameters . ValidateParameters ( ) ;
274- var plan = await ( GetFilterQueryPlanAsync ( collection , queryExpression , queryParameters , false , cancellationToken ) ) . ConfigureAwait ( false ) ;
275258
276- await ( AutoFlushIfRequiredAsync ( plan . QuerySpaces , cancellationToken ) ) . ConfigureAwait ( false ) ;
259+ var isFilter = filterConnection != null ;
260+ var plan = isFilter
261+ ? await ( GetFilterQueryPlanAsync ( filterConnection , queryExpression , queryParameters , false , cancellationToken ) ) . ConfigureAwait ( false )
262+ : GetHQLQueryPlan ( queryExpression , false ) ;
263+
264+ // GetFilterQueryPlan has already auto flushed or fully flush.
265+ if ( ! isFilter )
266+ await ( AutoFlushIfRequiredAsync ( plan . QuerySpaces , cancellationToken ) ) . ConfigureAwait ( false ) ;
277267
278268 bool success = false ;
279269 using ( SuspendAutoFlush ( ) ) //stops flush being called multiple times if this method is recursively called
@@ -441,73 +431,39 @@ public override async Task<IQuery> CreateFilterAsync(object collection, IQueryEx
441431 }
442432 }
443433
444- private async Task < IQueryExpressionPlan > GetFilterQueryPlanAsync ( object collection , IQueryExpression queryExpression , QueryParameters parameters , bool shallow , CancellationToken cancellationToken )
434+ private Task < IQueryExpressionPlan > GetFilterQueryPlanAsync ( object collection , IQueryExpression queryExpression , QueryParameters parameters , bool shallow , CancellationToken cancellationToken )
445435 {
446- cancellationToken . ThrowIfCancellationRequested ( ) ;
447- using ( new SessionIdLoggingContext ( SessionId ) )
436+ if ( cancellationToken . IsCancellationRequested )
448437 {
449- CollectionEntry entry = persistenceContext . GetCollectionEntryOrNull ( collection ) ;
450- ICollectionPersister roleBeforeFlush = ( entry == null ) ? null : entry . LoadedPersister ;
451-
452- IQueryExpressionPlan plan ;
453- if ( roleBeforeFlush == null )
454- {
455- // if it was previously unreferenced, we need to flush in order to
456- // get its state into the database in order to execute query
457- await ( FlushAsync ( cancellationToken ) ) . ConfigureAwait ( false ) ;
458- entry = persistenceContext . GetCollectionEntryOrNull ( collection ) ;
459- ICollectionPersister roleAfterFlush = ( entry == null ) ? null : entry . LoadedPersister ;
460- if ( roleAfterFlush == null )
461- {
462- throw new QueryException ( "The collection was unreferenced" ) ;
463- }
464- plan = Factory . QueryPlanCache . GetFilterQueryPlan ( queryExpression , roleAfterFlush . Role , shallow , EnabledFilters ) ;
465- }
466- else
467- {
468- // otherwise, we only need to flush if there are in-memory changes
469- // to the queried tables
470- plan = Factory . QueryPlanCache . GetFilterQueryPlan ( queryExpression , roleBeforeFlush . Role , shallow , EnabledFilters ) ;
471-
472- if ( await ( AutoFlushIfRequiredAsync ( plan . QuerySpaces , cancellationToken ) ) . ConfigureAwait ( false ) )
473- {
474- // might need to run a different filter entirely after the flush
475- // because the collection role may have changed
476- entry = persistenceContext . GetCollectionEntryOrNull ( collection ) ;
477- ICollectionPersister roleAfterFlush = ( entry == null ) ? null : entry . LoadedPersister ;
478- if ( roleBeforeFlush != roleAfterFlush )
479- {
480- if ( roleAfterFlush == null )
481- {
482- throw new QueryException ( "The collection was dereferenced" ) ;
483- }
484- plan = Factory . QueryPlanCache . GetFilterQueryPlan ( queryExpression , roleAfterFlush . Role , shallow , EnabledFilters ) ;
485- }
486- }
487- }
488-
489- if ( parameters != null )
490- {
491- parameters . PositionalParameterValues [ 0 ] = entry . LoadedKey ;
492- parameters . PositionalParameterTypes [ 0 ] = entry . LoadedPersister . KeyType ;
493- }
438+ return Task . FromCanceled < IQueryExpressionPlan > ( cancellationToken ) ;
439+ }
440+ return GetFilterQueryPlanAsync ( collection , parameters , shallow , null , queryExpression , cancellationToken ) ;
441+ }
494442
495- return plan ;
443+ private Task < IQueryExpressionPlan > GetFilterQueryPlanAsync ( object collection , string filter , QueryParameters parameters , bool shallow , CancellationToken cancellationToken )
444+ {
445+ if ( cancellationToken . IsCancellationRequested )
446+ {
447+ return Task . FromCanceled < IQueryExpressionPlan > ( cancellationToken ) ;
496448 }
449+ return GetFilterQueryPlanAsync ( collection , parameters , shallow , filter , null , cancellationToken ) ;
497450 }
498451
499- private async Task < IQueryExpressionPlan > GetFilterQueryPlanAsync ( object collection , string filter , QueryParameters parameters , bool shallow , CancellationToken cancellationToken )
452+ private async Task < IQueryExpressionPlan > GetFilterQueryPlanAsync ( object collection , QueryParameters parameters , bool shallow ,
453+ string filter , IQueryExpression queryExpression , CancellationToken cancellationToken )
500454 {
501455 cancellationToken . ThrowIfCancellationRequested ( ) ;
502456 using ( new SessionIdLoggingContext ( SessionId ) )
503457 {
504458 if ( collection == null )
505- {
506- throw new ArgumentNullException ( "collection" , "null collection passed to filter" ) ;
507- }
459+ throw new ArgumentNullException ( nameof ( collection ) , "null collection passed to filter" ) ;
460+ if ( filter != null && queryExpression != null )
461+ throw new ArgumentException ( $ "Either { nameof ( filter ) } or { nameof ( queryExpression ) } must be specified, not both.") ;
462+ if ( filter == null && queryExpression == null )
463+ throw new ArgumentException ( $ "{ nameof ( filter ) } and { nameof ( queryExpression ) } were both null.") ;
508464
509- CollectionEntry entry = persistenceContext . GetCollectionEntryOrNull ( collection ) ;
510- ICollectionPersister roleBeforeFlush = ( entry == null ) ? null : entry . LoadedPersister ;
465+ var entry = persistenceContext . GetCollectionEntryOrNull ( collection ) ;
466+ var roleBeforeFlush = entry ? . LoadedPersister ;
511467
512468 IQueryExpressionPlan plan ;
513469 if ( roleBeforeFlush == null )
@@ -516,31 +472,31 @@ private async Task<IQueryExpressionPlan> GetFilterQueryPlanAsync(object collecti
516472 // get its state into the database in order to execute query
517473 await ( FlushAsync ( cancellationToken ) ) . ConfigureAwait ( false ) ;
518474 entry = persistenceContext . GetCollectionEntryOrNull ( collection ) ;
519- ICollectionPersister roleAfterFlush = ( entry == null ) ? null : entry . LoadedPersister ;
475+ var roleAfterFlush = entry ? . LoadedPersister ;
520476 if ( roleAfterFlush == null )
521477 {
522478 throw new QueryException ( "The collection was unreferenced" ) ;
523479 }
524- plan = Factory . QueryPlanCache . GetFilterQueryPlan ( filter , roleAfterFlush . Role , shallow , EnabledFilters ) ;
480+ plan = GetFilterQueryPlan ( roleAfterFlush . Role , shallow , filter , queryExpression ) ;
525481 }
526482 else
527483 {
528484 // otherwise, we only need to flush if there are in-memory changes
529485 // to the queried tables
530- plan = Factory . QueryPlanCache . GetFilterQueryPlan ( filter , roleBeforeFlush . Role , shallow , EnabledFilters ) ;
486+ plan = GetFilterQueryPlan ( roleBeforeFlush . Role , shallow , filter , queryExpression ) ;
531487 if ( await ( AutoFlushIfRequiredAsync ( plan . QuerySpaces , cancellationToken ) ) . ConfigureAwait ( false ) )
532488 {
533489 // might need to run a different filter entirely after the flush
534490 // because the collection role may have changed
535491 entry = persistenceContext . GetCollectionEntryOrNull ( collection ) ;
536- ICollectionPersister roleAfterFlush = ( entry == null ) ? null : entry . LoadedPersister ;
492+ var roleAfterFlush = entry ? . LoadedPersister ;
537493 if ( roleBeforeFlush != roleAfterFlush )
538494 {
539495 if ( roleAfterFlush == null )
540496 {
541497 throw new QueryException ( "The collection was dereferenced" ) ;
542498 }
543- plan = Factory . QueryPlanCache . GetFilterQueryPlan ( filter , roleAfterFlush . Role , shallow , EnabledFilters ) ;
499+ plan = GetFilterQueryPlan ( roleAfterFlush . Role , shallow , filter , queryExpression ) ;
544500 }
545501 }
546502 }
0 commit comments