@@ -320,10 +320,18 @@ private async Task<IList> DoQueryAsync(ISessionImplementor session, QueryParamet
320
320
}
321
321
}
322
322
323
- internal async Task InitializeEntitiesAndCollectionsAsync ( IList hydratedObjects , object resultSetId , ISessionImplementor session , bool readOnly , CancellationToken cancellationToken )
323
+ internal Task InitializeEntitiesAndCollectionsAsync ( IList hydratedObjects , DbDataReader resultSetId , ISessionImplementor session , bool readOnly , CancellationToken cancellationToken )
324
+ {
325
+ if ( cancellationToken . IsCancellationRequested )
326
+ {
327
+ return Task . FromCanceled < object > ( cancellationToken ) ;
328
+ }
329
+ return InitializeEntitiesAndCollectionsAsync ( hydratedObjects , resultSetId , session , readOnly , CollectionPersisters , cancellationToken ) ;
330
+ }
331
+
332
+ internal static async Task InitializeEntitiesAndCollectionsAsync ( IList hydratedObjects , DbDataReader resultSetId , ISessionImplementor session , bool readOnly , ICollectionPersister [ ] collectionPersisters , CancellationToken cancellationToken )
324
333
{
325
334
cancellationToken . ThrowIfCancellationRequested ( ) ;
326
- ICollectionPersister [ ] collectionPersisters = CollectionPersisters ;
327
335
if ( collectionPersisters != null )
328
336
{
329
337
for ( int i = 0 ; i < collectionPersisters . Length ; i ++ )
@@ -543,7 +551,7 @@ private async Task<EntityKey> GetKeyFromResultSetAsync(int i, IEntityPersister p
543
551
/// if the version numbers are different.
544
552
/// </summary>
545
553
/// <exception cref="StaleObjectStateException"></exception>
546
- private async Task CheckVersionAsync ( int i , IEntityPersister persister , object id , object entity , DbDataReader rs , ISessionImplementor session , CancellationToken cancellationToken )
554
+ private static async Task CheckVersionAsync ( IEntityPersister persister , object id , object entity , DbDataReader rs , ISessionImplementor session , IEntityAliases entityAliases , CancellationToken cancellationToken )
547
555
{
548
556
cancellationToken . ThrowIfCancellationRequested ( ) ;
549
557
object version = session . PersistenceContext . GetEntry ( entity ) . Version ;
@@ -552,7 +560,7 @@ private async Task CheckVersionAsync(int i, IEntityPersister persister, object i
552
560
if ( version != null )
553
561
{
554
562
IVersionType versionType = persister . VersionType ;
555
- object currentVersion = await ( versionType . NullSafeGetAsync ( rs , EntityAliases [ i ] . SuffixedVersionAliases , session , null , cancellationToken ) ) . ConfigureAwait ( false ) ;
563
+ object currentVersion = await ( versionType . NullSafeGetAsync ( rs , entityAliases . SuffixedVersionAliases , session , null , cancellationToken ) ) . ConfigureAwait ( false ) ;
556
564
if ( ! versionType . IsEqual ( version , currentVersion ) )
557
565
{
558
566
if ( session . Factory . Statistics . IsStatisticsEnabled )
@@ -577,7 +585,6 @@ private async Task<object[]> GetRowAsync(DbDataReader rs, ILoadable[] persisters
577
585
{
578
586
cancellationToken . ThrowIfCancellationRequested ( ) ;
579
587
int cols = persisters . Length ;
580
- IEntityAliases [ ] descriptors = EntityAliases ;
581
588
582
589
if ( Log . IsDebugEnabled ( ) )
583
590
{
@@ -586,6 +593,7 @@ private async Task<object[]> GetRowAsync(DbDataReader rs, ILoadable[] persisters
586
593
587
594
object [ ] rowResults = new object [ cols ] ;
588
595
596
+ var upgradeLocks = UpgradeLocks ( ) ;
589
597
for ( int i = 0 ; i < cols ; i ++ )
590
598
{
591
599
object obj = null ;
@@ -601,31 +609,62 @@ private async Task<object[]> GetRowAsync(DbDataReader rs, ILoadable[] persisters
601
609
}
602
610
else
603
611
{
604
- //If the object is already loaded, return the loaded one
605
- obj = await ( session . GetEntityUsingInterceptorAsync ( key , cancellationToken ) ) . ConfigureAwait ( false ) ;
606
- if ( obj != null )
607
- {
608
- //its already loaded so dont need to hydrate it
609
- await ( InstanceAlreadyLoadedAsync ( rs , i , persisters [ i ] , key , obj , lockModes [ i ] , session , cancellationToken ) ) . ConfigureAwait ( false ) ;
610
- }
611
- else
612
- {
613
- obj =
614
- await ( InstanceNotYetLoadedAsync ( rs , i , persisters [ i ] , key , lockModes [ i ] , descriptors [ i ] . RowIdAlias , optionalObjectKey ,
615
- optionalObject , hydratedObjects , session , cancellationToken ) ) . ConfigureAwait ( false ) ;
616
- }
612
+ obj = await ( GetOrCreateEntityFromDataReaderAsync (
613
+ rs ,
614
+ optionalObject ,
615
+ optionalObjectKey ,
616
+ hydratedObjects ,
617
+ session ,
618
+ key ,
619
+ persisters [ i ] ,
620
+ lockModes [ i ] ,
621
+ EntityAliases [ i ] ,
622
+ upgradeLocks ,
623
+ IsEagerPropertyFetchEnabled ( i ) ,
624
+ OwnerAssociationTypes ? [ i ] , cancellationToken ) ) . ConfigureAwait ( false ) ;
617
625
}
618
626
619
627
rowResults [ i ] = obj ;
620
628
}
621
629
return rowResults ;
622
630
}
623
631
632
+ /// <summary>
633
+ /// Returns either already loaded entity from session or creates new entity from data reader. Returned created entity is not fully initialized - it's added to <paramref name="hydratedObjects"/> collection. To fully initialize entity this collection needs to be supplied to <see cref="InitializeEntitiesAndCollectionsAsync(System.Collections.IList,System.Data.Common.DbDataReader,NHibernate.Engine.ISessionImplementor,bool,CancellationToken)"/>
634
+ /// </summary>
635
+ internal static async Task < object > GetOrCreateEntityFromDataReaderAsync ( DbDataReader rs , object optionalObject , EntityKey optionalObjectKey , IList hydratedObjects , ISessionImplementor session , EntityKey key , ILoadable persister , LockMode lockMode , IEntityAliases entityAliases , bool upgradeLocks , bool eagerPropertyFetch , EntityType ownerAssociationType , CancellationToken cancellationToken )
636
+ {
637
+ cancellationToken . ThrowIfCancellationRequested ( ) ;
638
+ //If the object is already loaded, return the loaded one
639
+ object obj = await ( session . GetEntityUsingInterceptorAsync ( key , cancellationToken ) ) . ConfigureAwait ( false ) ;
640
+ if ( obj != null )
641
+ {
642
+ //its already loaded so dont need to hydrate it
643
+ await ( InstanceAlreadyLoadedAsync ( rs , persister , key , obj , lockMode , session , entityAliases , upgradeLocks , cancellationToken ) ) . ConfigureAwait ( false ) ;
644
+ }
645
+ else
646
+ {
647
+ obj =
648
+ await ( InstanceNotYetLoadedAsync (
649
+ rs ,
650
+ persister ,
651
+ key ,
652
+ lockMode ,
653
+ optionalObjectKey ,
654
+ optionalObject ,
655
+ hydratedObjects ,
656
+ session ,
657
+ entityAliases ,
658
+ eagerPropertyFetch ,
659
+ ownerAssociationType , cancellationToken ) ) . ConfigureAwait ( false ) ;
660
+ }
661
+ return obj ;
662
+ }
663
+
624
664
/// <summary>
625
665
/// The entity instance is already in the session cache
626
666
/// </summary>
627
- private async Task InstanceAlreadyLoadedAsync ( DbDataReader rs , int i , IEntityPersister persister , EntityKey key , object obj ,
628
- LockMode lockMode , ISessionImplementor session , CancellationToken cancellationToken )
667
+ private static async Task InstanceAlreadyLoadedAsync ( DbDataReader rs , IEntityPersister persister , EntityKey key , object obj , LockMode lockMode , ISessionImplementor session , IEntityAliases entityAliases , bool upgradeLocks , CancellationToken cancellationToken )
629
668
{
630
669
cancellationToken . ThrowIfCancellationRequested ( ) ;
631
670
if ( ! persister . IsInstance ( obj ) )
@@ -634,7 +673,7 @@ private async Task InstanceAlreadyLoadedAsync(DbDataReader rs, int i, IEntityPer
634
673
throw new WrongClassException ( errorMsg , key . Identifier , persister . EntityName ) ;
635
674
}
636
675
637
- if ( LockMode . None != lockMode && UpgradeLocks ( ) )
676
+ if ( LockMode . None != lockMode && upgradeLocks )
638
677
{
639
678
EntityEntry entry = session . PersistenceContext . GetEntry ( obj ) ;
640
679
bool isVersionCheckNeeded = persister . IsVersioned && entry . LockMode . LessThan ( lockMode ) ;
@@ -645,7 +684,7 @@ private async Task InstanceAlreadyLoadedAsync(DbDataReader rs, int i, IEntityPer
645
684
if ( isVersionCheckNeeded )
646
685
{
647
686
// we only check the version when _upgrading_ lock modes
648
- await ( CheckVersionAsync ( i , persister , key . Identifier , obj , rs , session , cancellationToken ) ) . ConfigureAwait ( false ) ;
687
+ await ( CheckVersionAsync ( persister , key . Identifier , obj , rs , session , entityAliases , cancellationToken ) ) . ConfigureAwait ( false ) ;
649
688
// we need to upgrade the lock mode to the mode requested
650
689
entry . LockMode = lockMode ;
651
690
}
@@ -655,14 +694,12 @@ private async Task InstanceAlreadyLoadedAsync(DbDataReader rs, int i, IEntityPer
655
694
/// <summary>
656
695
/// The entity instance is not in the session cache
657
696
/// </summary>
658
- private async Task < object > InstanceNotYetLoadedAsync ( DbDataReader dr , int i , ILoadable persister , EntityKey key , LockMode lockMode ,
659
- string rowIdAlias , EntityKey optionalObjectKey , object optionalObject ,
660
- IList hydratedObjects , ISessionImplementor session , CancellationToken cancellationToken )
697
+ private static async Task < object > InstanceNotYetLoadedAsync ( DbDataReader dr , ILoadable persister , EntityKey key , LockMode lockMode , EntityKey optionalObjectKey , object optionalObject , IList hydratedObjects , ISessionImplementor session , IEntityAliases entityAliases , bool eagerPropertyFetch , EntityType ownerAssociationType , CancellationToken cancellationToken )
661
698
{
662
699
cancellationToken . ThrowIfCancellationRequested ( ) ;
663
700
object obj ;
664
701
665
- string instanceClass = await ( GetInstanceClassAsync ( dr , i , persister , key . Identifier , session , cancellationToken ) ) . ConfigureAwait ( false ) ;
702
+ string instanceClass = await ( GetInstanceClassAsync ( dr , persister , key . Identifier , session , entityAliases , cancellationToken ) ) . ConfigureAwait ( false ) ;
666
703
667
704
if ( optionalObjectKey != null && key . Equals ( optionalObjectKey ) )
668
705
{
@@ -680,7 +717,7 @@ private async Task<object> InstanceNotYetLoadedAsync(DbDataReader dr, int i, ILo
680
717
// (but don't yet initialize the object itself)
681
718
// note that we acquired LockMode.READ even if it was not requested
682
719
LockMode acquiredLockMode = lockMode == LockMode . None ? LockMode . Read : lockMode ;
683
- await ( LoadFromResultSetAsync ( dr , i , obj , instanceClass , key , rowIdAlias , acquiredLockMode , persister , session , cancellationToken ) ) . ConfigureAwait ( false ) ;
720
+ await ( LoadFromResultSetAsync ( dr , obj , instanceClass , key , acquiredLockMode , persister , session , eagerPropertyFetch , entityAliases , ownerAssociationType , cancellationToken ) ) . ConfigureAwait ( false ) ;
684
721
685
722
// materialize associations (and initialize the object) later
686
723
hydratedObjects . Add ( obj ) ;
@@ -693,41 +730,39 @@ private async Task<object> InstanceNotYetLoadedAsync(DbDataReader dr, int i, ILo
693
730
/// an array of "hydrated" values (do not resolve associations yet),
694
731
/// and pass the hydrated state to the session.
695
732
/// </summary>
696
- private async Task LoadFromResultSetAsync ( DbDataReader rs , int i , object obj , string instanceClass , EntityKey key ,
697
- string rowIdAlias , LockMode lockMode , ILoadable rootPersister ,
698
- ISessionImplementor session , CancellationToken cancellationToken )
733
+ private static async Task LoadFromResultSetAsync ( DbDataReader rs , object obj , string instanceClass , EntityKey key , LockMode lockMode , ILoadable rootPersister ,
734
+ ISessionImplementor session , bool eagerPropertyFetch , IEntityAliases entityAlias , EntityType ownerAssociationType , CancellationToken cancellationToken )
699
735
{
700
736
cancellationToken . ThrowIfCancellationRequested ( ) ;
701
737
object id = key . Identifier ;
702
738
703
739
// Get the persister for the _subclass_
704
- ILoadable persister = ( ILoadable ) Factory . GetEntityPersister ( instanceClass ) ;
740
+ ILoadable persister = rootPersister . HasSubclasses
741
+ ? ( ILoadable ) session . Factory . GetEntityPersister ( instanceClass )
742
+ : rootPersister ;
705
743
706
744
if ( Log . IsDebugEnabled ( ) )
707
745
{
708
746
Log . Debug ( "Initializing object from DataReader: {0}" , MessageHelper . InfoString ( persister , id ) ) ;
709
747
}
710
748
711
- bool eagerPropertyFetch = IsEagerPropertyFetchEnabled ( i ) ;
712
-
713
749
// add temp entry so that the next step is circular-reference
714
750
// safe - only needed because some types don't take proper
715
751
// advantage of two-phase-load (esp. components)
716
752
TwoPhaseLoad . AddUninitializedEntity ( key , obj , persister , lockMode , ! eagerPropertyFetch , session ) ;
717
753
718
754
// This is not very nice (and quite slow):
719
755
string [ ] [ ] cols = persister == rootPersister
720
- ? EntityAliases [ i ] . SuffixedPropertyAliases
721
- : EntityAliases [ i ] . GetSuffixedPropertyAliases ( persister ) ;
756
+ ? entityAlias . SuffixedPropertyAliases
757
+ : entityAlias . GetSuffixedPropertyAliases ( persister ) ;
722
758
723
759
object [ ] values = await ( persister . HydrateAsync ( rs , id , obj , rootPersister , cols , eagerPropertyFetch , session , cancellationToken ) ) . ConfigureAwait ( false ) ;
724
760
725
- object rowId = persister . HasRowId ? rs [ rowIdAlias ] : null ;
761
+ object rowId = persister . HasRowId ? rs [ entityAlias . RowIdAlias ] : null ;
726
762
727
- IAssociationType [ ] ownerAssociationTypes = OwnerAssociationTypes ;
728
- if ( ownerAssociationTypes != null && ownerAssociationTypes [ i ] != null )
763
+ if ( ownerAssociationType != null )
729
764
{
730
- string ukName = ownerAssociationTypes [ i ] . RHSUniqueKeyPropertyName ;
765
+ string ukName = ownerAssociationType . RHSUniqueKeyPropertyName ;
731
766
if ( ukName != null )
732
767
{
733
768
int index = ( ( IUniqueKeyLoadable ) persister ) . GetPropertyIndex ( ukName ) ;
@@ -750,14 +785,14 @@ private async Task LoadFromResultSetAsync(DbDataReader rs, int i, object obj, st
750
785
/// <summary>
751
786
/// Determine the concrete class of an instance for the <c>DbDataReader</c>
752
787
/// </summary>
753
- private async Task < string > GetInstanceClassAsync ( DbDataReader rs , int i , ILoadable persister , object id , ISessionImplementor session , CancellationToken cancellationToken )
788
+ private static async Task < string > GetInstanceClassAsync ( DbDataReader rs , ILoadable persister , object id , ISessionImplementor session , IEntityAliases entityAliases , CancellationToken cancellationToken )
754
789
{
755
790
cancellationToken . ThrowIfCancellationRequested ( ) ;
756
791
if ( persister . HasSubclasses )
757
792
{
758
793
// code to handle subclasses of topClass
759
794
object discriminatorValue =
760
- await ( persister . DiscriminatorType . NullSafeGetAsync ( rs , EntityAliases [ i ] . SuffixedDiscriminatorAlias , session , null , cancellationToken ) ) . ConfigureAwait ( false ) ;
795
+ await ( persister . DiscriminatorType . NullSafeGetAsync ( rs , entityAliases . SuffixedDiscriminatorAlias , session , null , cancellationToken ) ) . ConfigureAwait ( false ) ;
761
796
762
797
string result = persister . GetSubclassForDiscriminatorValue ( discriminatorValue ) ;
763
798
0 commit comments