@@ -17,6 +17,7 @@ public class TriggersOptionExtension : IDbContextOptionsExtension
1717 sealed class ExtensionInfo : DbContextOptionsExtensionInfo
1818 {
1919 private string ? _logFragment ;
20+ private int ? _serviceProviderHashCode ;
2021 public ExtensionInfo ( IDbContextOptionsExtension extension ) : base ( extension )
2122 {
2223 }
@@ -44,14 +45,19 @@ public override void PopulateDebugInfo(IDictionary<string, string> debugInfo)
4445 throw new ArgumentNullException ( nameof ( debugInfo ) ) ;
4546 }
4647
47- debugInfo [ "Triggers:TriggersCount" ] = ( Extension . _triggers ? . Count ( ) ?? 0 ) . ToString ( ) ;
48- debugInfo [ "Triggers:TriggerTypesCount" ] = ( Extension . _triggerTypes ? . Count ( ) ?? 0 ) . ToString ( ) ;
48+ debugInfo [ "Triggers:TriggersCount" ] = ( Extension . _triggers ? . Count ?? 0 ) . ToString ( ) ;
49+ debugInfo [ "Triggers:TriggerTypesCount" ] = ( Extension . _triggerTypes ? . Count ?? 0 ) . ToString ( ) ;
4950 debugInfo [ "Triggers:MaxCascadeCycles" ] = Extension . _maxCascadeCycles . ToString ( ) ;
5051 debugInfo [ "Triggers:CascadeBehavior" ] = Extension . _cascadeBehavior . ToString ( ) ;
5152 }
5253
5354 public override int GetServiceProviderHashCode ( )
5455 {
56+ if ( _serviceProviderHashCode . HasValue )
57+ {
58+ return _serviceProviderHashCode . Value ;
59+ }
60+
5561 var hashCode = new HashCode ( ) ;
5662
5763 if ( Extension . _triggers != null )
@@ -78,28 +84,56 @@ public override int GetServiceProviderHashCode()
7884 hashCode . Add ( Extension . _serviceProviderTransform ) ;
7985 }
8086
81- return hashCode . ToHashCode ( ) ;
87+ _serviceProviderHashCode = hashCode . ToHashCode ( ) ;
88+ return _serviceProviderHashCode . Value ;
8289 }
8390
8491 public override bool ShouldUseSameServiceProvider ( DbContextOptionsExtensionInfo other )
85- => other is ExtensionInfo otherInfo
86- && Enumerable . SequenceEqual ( Extension . _triggers ?? Enumerable . Empty < ValueTuple < object , ServiceLifetime > > ( ) , otherInfo . Extension . _triggers ?? Enumerable . Empty < ValueTuple < object , ServiceLifetime > > ( ) )
87- && Enumerable . SequenceEqual ( Extension . _triggerTypes ?? Enumerable . Empty < Type > ( ) , otherInfo . Extension . _triggerTypes ?? Enumerable . Empty < Type > ( ) )
88- && Extension . _maxCascadeCycles == otherInfo . Extension . _maxCascadeCycles
89- && Extension . _cascadeBehavior == otherInfo . Extension . _cascadeBehavior
90- && Extension . _serviceProviderTransform == otherInfo . Extension . _serviceProviderTransform ;
92+ {
93+ if ( other is not ExtensionInfo otherInfo )
94+ {
95+ return false ;
96+ }
97+
98+ // Check cheap scalar comparisons first
99+ if ( Extension . _maxCascadeCycles != otherInfo . Extension . _maxCascadeCycles
100+ || Extension . _cascadeBehavior != otherInfo . Extension . _cascadeBehavior
101+ || Extension . _serviceProviderTransform != otherInfo . Extension . _serviceProviderTransform )
102+ {
103+ return false ;
104+ }
105+
106+ // Check list counts before doing full sequence comparison
107+ var triggersCount = Extension . _triggers ? . Count ?? 0 ;
108+ var otherTriggersCount = otherInfo . Extension . _triggers ? . Count ?? 0 ;
109+ if ( triggersCount != otherTriggersCount )
110+ {
111+ return false ;
112+ }
113+
114+ var triggerTypesCount = Extension . _triggerTypes ? . Count ?? 0 ;
115+ var otherTriggerTypesCount = otherInfo . Extension . _triggerTypes ? . Count ?? 0 ;
116+ if ( triggerTypesCount != otherTriggerTypesCount )
117+ {
118+ return false ;
119+ }
120+
121+ // Full sequence comparison only when counts match
122+ return Enumerable . SequenceEqual ( Extension . _triggers ?? Enumerable . Empty < ValueTuple < object , ServiceLifetime > > ( ) , otherInfo . Extension . _triggers ?? Enumerable . Empty < ValueTuple < object , ServiceLifetime > > ( ) )
123+ && Enumerable . SequenceEqual ( Extension . _triggerTypes ?? Enumerable . Empty < Type > ( ) , otherInfo . Extension . _triggerTypes ?? Enumerable . Empty < Type > ( ) ) ;
124+ }
91125 }
92126
93127 private ExtensionInfo ? _info ;
94- private IEnumerable < ( object typeOrInstance , ServiceLifetime lifetime ) > ? _triggers ;
95- private IEnumerable < Type > _triggerTypes ;
128+ private List < ( object typeOrInstance , ServiceLifetime lifetime ) > ? _triggers ;
129+ private List < Type > _triggerTypes ;
96130 private int _maxCascadeCycles = 100 ;
97131 private CascadeBehavior _cascadeBehavior = CascadeBehavior . EntityAndType ;
98132 private Func < IServiceProvider , IServiceProvider > ? _serviceProviderTransform ;
99133
100134 public TriggersOptionExtension ( )
101135 {
102- _triggerTypes = new [ ] {
136+ _triggerTypes = new List < Type > {
103137 typeof ( IBeforeSaveTrigger < > ) ,
104138 typeof ( IBeforeSaveAsyncTrigger < > ) ,
105139 typeof ( IAfterSaveTrigger < > ) ,
@@ -125,10 +159,10 @@ public TriggersOptionExtension(TriggersOptionExtension copyFrom)
125159 {
126160 if ( copyFrom . _triggers != null )
127161 {
128- _triggers = copyFrom . _triggers ;
162+ _triggers = new List < ( object typeOrInstance , ServiceLifetime lifetime ) > ( copyFrom . _triggers ) ;
129163 }
130164
131- _triggerTypes = copyFrom . _triggerTypes ;
165+ _triggerTypes = new List < Type > ( copyFrom . _triggerTypes ) ;
132166 _maxCascadeCycles = copyFrom . _maxCascadeCycles ;
133167 _cascadeBehavior = copyFrom . _cascadeBehavior ;
134168 _serviceProviderTransform = copyFrom . _serviceProviderTransform ;
@@ -263,17 +297,8 @@ public TriggersOptionExtension WithAdditionalTrigger(Type triggerType, ServiceLi
263297 }
264298
265299 var clone = Clone ( ) ;
266- var triggerEnumerable = Enumerable . Repeat ( ( ( object ) triggerType , lifetime ) , 1 ) ;
267-
268- if ( clone . _triggers == null )
269- {
270- clone . _triggers = triggerEnumerable ;
271- }
272- else
273- {
274- clone . _triggers = clone . _triggers . Concat ( triggerEnumerable ) ;
275- }
276-
300+ clone . _triggers ??= new List < ( object typeOrInstance , ServiceLifetime lifetime ) > ( ) ;
301+ clone . _triggers . Add ( ( ( object ) triggerType , lifetime ) ) ;
277302
278303 return clone ;
279304 }
@@ -291,17 +316,8 @@ public TriggersOptionExtension WithAdditionalTrigger(object instance)
291316 }
292317
293318 var clone = Clone ( ) ;
294- var triggersEnumerable = Enumerable . Repeat ( ( instance , ServiceLifetime . Singleton ) , 1 ) ;
295-
296- if ( clone . _triggers == null )
297- {
298- clone . _triggers = triggersEnumerable ;
299- }
300- else
301- {
302- clone . _triggers = clone . _triggers . Concat ( triggersEnumerable ) ;
303- }
304-
319+ clone . _triggers ??= new List < ( object typeOrInstance , ServiceLifetime lifetime ) > ( ) ;
320+ clone . _triggers . Add ( ( instance , ServiceLifetime . Singleton ) ) ;
305321
306322 return clone ;
307323 }
@@ -313,19 +329,9 @@ public TriggersOptionExtension WithAdditionalTriggerType(Type triggerType)
313329 throw new ArgumentNullException ( nameof ( triggerType ) ) ;
314330 }
315331
316-
317332 var clone = Clone ( ) ;
318- var triggerTypesEnumerable = Enumerable . Repeat ( triggerType , 1 ) ;
319-
320- if ( clone . _triggerTypes == null )
321- {
322- clone . _triggerTypes = triggerTypesEnumerable ;
323- }
324- else
325- {
326- clone . _triggerTypes = clone . _triggerTypes . Concat ( triggerTypesEnumerable ) ;
327- }
328-
333+ clone . _triggerTypes ??= new List < Type > ( ) ;
334+ clone . _triggerTypes . Add ( triggerType ) ;
329335
330336 return clone ;
331337 }
0 commit comments