33using System . Globalization ;
44using Microsoft . Xrm . Sdk . Metadata ;
55using Microsoft . Xrm . Sdk . Messages ;
6+ using System . Collections . Concurrent ;
67
78namespace Microsoft . PowerPlatform . Cds . Client
89{
@@ -15,19 +16,19 @@ internal class MetadataUtility
1516 /// <summary>
1617 /// MetadataCache object.
1718 /// </summary>
18- private Dictionary < String , EntityMetadata > _entityMetadataCache = new Dictionary < String , EntityMetadata > ( ) ;
19+ private ConcurrentDictionary < String , EntityMetadata > _entityMetadataCache = new ConcurrentDictionary < String , EntityMetadata > ( ) ;
1920 /// <summary>
2021 /// Attribute metadata cache object
2122 /// </summary>
22- private Dictionary < String , AttributeMetadata > _attributeMetadataCache = new Dictionary < String , AttributeMetadata > ( ) ;
23+ private ConcurrentDictionary < String , AttributeMetadata > _attributeMetadataCache = new ConcurrentDictionary < String , AttributeMetadata > ( ) ;
2324 /// <summary>
2425 /// Global option metadata cache object.
2526 /// </summary>
26- private Dictionary < String , OptionSetMetadata > _globalOptionMetadataCache = new Dictionary < String , OptionSetMetadata > ( ) ;
27+ private ConcurrentDictionary < String , OptionSetMetadata > _globalOptionMetadataCache = new ConcurrentDictionary < String , OptionSetMetadata > ( ) ;
2728 /// <summary>
2829 /// Entity Name catch object
2930 /// </summary>
30- private Dictionary < int , string > _entityNameCache = new Dictionary < int , string > ( ) ;
31+ private ConcurrentDictionary < int , string > _entityNameCache = new ConcurrentDictionary < int , string > ( ) ;
3132 /// <summary>
3233 /// Lock object
3334 /// </summary>
@@ -52,13 +53,17 @@ public MetadataUtility(CdsServiceClient svcActions)
5253 /// <param name="entityName"></param>
5354 public void ClearCachedEntityMetadata ( string entityName )
5455 {
56+ TouchMetadataDate ( ) ;
5557 // Not clearing the ETC ID's as they do not change...
56- lock ( _lockObject )
58+ if ( _entityMetadataCache . ContainsKey ( entityName ) )
5759 {
58- if ( _entityMetadataCache . ContainsKey ( entityName ) )
59- _entityMetadataCache . Remove ( entityName ) ;
60- if ( _attributeMetadataCache . ContainsKey ( entityName ) )
61- _attributeMetadataCache . Remove ( entityName ) ;
60+ EntityMetadata removedEntData ;
61+ _entityMetadataCache . TryRemove ( entityName , out removedEntData ) ;
62+ }
63+ if ( _attributeMetadataCache . ContainsKey ( entityName ) )
64+ {
65+ AttributeMetadata removedAttribData ;
66+ _attributeMetadataCache . TryRemove ( entityName , out removedAttribData ) ;
6267 }
6368 }
6469
@@ -82,21 +87,19 @@ public List<EntityMetadata> GetAllEntityMetadata(bool onlyPublished, EntityFilte
8287 {
8388 foreach ( var entity in response . EntityMetadata )
8489 {
85- lock ( _lockObject )
86- {
87- if ( _entityMetadataCache . ContainsKey ( entity . LogicalName ) )
88- _entityMetadataCache [ entity . LogicalName ] = entity ; // Update local copy of the entity...
89- else
90- _entityMetadataCache . Add ( entity . LogicalName , entity ) ;
91-
92- results . Add ( entity ) ;
93- // Preload the entity data catch as this has been called already
94- if ( _entityNameCache . ContainsKey ( entity . ObjectTypeCode . Value ) )
95- continue ;
96- else
97- _entityNameCache . Add ( entity . ObjectTypeCode . Value , entity . LogicalName ) ;
98- }
90+ if ( _entityMetadataCache . ContainsKey ( entity . LogicalName ) )
91+ _entityMetadataCache [ entity . LogicalName ] = entity ; // Update local copy of the entity...
92+ else
93+ _entityMetadataCache . TryAdd ( entity . LogicalName , entity ) ;
94+
95+ results . Add ( entity ) ;
96+ // Preload the entity data catch as this has been called already
97+ if ( _entityNameCache . ContainsKey ( entity . ObjectTypeCode . Value ) )
98+ continue ;
99+ else
100+ _entityNameCache . TryAdd ( entity . ObjectTypeCode . Value , entity . LogicalName ) ;
99101 }
102+ TouchMetadataDate ( ) ;
100103 }
101104
102105 return results ;
@@ -169,16 +172,13 @@ public EntityMetadata GetEntityMetadata(EntityFilters requestType, String entity
169172 if ( response != null )
170173 {
171174 entityMetadata = response . EntityMetadata ;
172- lock ( _lockObject )
173- {
174- if ( ! _entityMetadataCache . ContainsKey ( entityName ) )
175- _entityMetadataCache . Add ( entityName , entityMetadata ) ;
176- else
177- _entityMetadataCache [ entityName ] = entityMetadata ;
175+ if ( ! _entityMetadataCache . ContainsKey ( entityName ) )
176+ _entityMetadataCache . TryAdd ( entityName , entityMetadata ) ;
177+ else
178+ _entityMetadataCache [ entityName ] = entityMetadata ;
178179
179- if ( ! bSelectiveUpdate )
180- _metadataLastValidatedAt = DateTime . Now ;
181- }
180+ if ( ! bSelectiveUpdate )
181+ TouchMetadataDate ( ) ;
182182 }
183183 }
184184 return entityMetadata ;
@@ -204,20 +204,17 @@ public string GetEntityLogicalName(int entityTypeCode)
204204 RetrieveAllEntitiesResponse response = ( RetrieveAllEntitiesResponse ) svcAct . CdsCommand_Execute ( request , "GetEntityLogicalName" ) ;
205205 if ( response != null )
206206 {
207- lock ( _lockObject )
207+ foreach ( EntityMetadata metadata in response . EntityMetadata )
208208 {
209- foreach ( EntityMetadata metadata in response . EntityMetadata )
210- {
211- _entityNameCache . Add ( metadata . ObjectTypeCode . Value , metadata . LogicalName ) ;
212-
213- // reload metadata cache.
214- if ( _entityMetadataCache . ContainsKey ( metadata . LogicalName ) )
215- continue ;
216- else
217- _entityMetadataCache . Add ( metadata . LogicalName , metadata ) ;
218- }
219- _metadataLastValidatedAt = DateTime . Now ;
209+ _entityNameCache . TryAdd ( metadata . ObjectTypeCode . Value , metadata . LogicalName ) ;
210+
211+ // reload metadata cache.
212+ if ( _entityMetadataCache . ContainsKey ( metadata . LogicalName ) )
213+ continue ;
214+ else
215+ _entityMetadataCache . TryAdd ( metadata . LogicalName , metadata ) ;
220216 }
217+ TouchMetadataDate ( ) ;
221218 }
222219 }
223220 }
@@ -249,11 +246,8 @@ public AttributeMetadata GetAttributeMetadata(string entityName, string attribut
249246 if ( response != null )
250247 {
251248 attributeMetadata = response . AttributeMetadata ;
252- lock ( _lockObject )
253- {
254- _attributeMetadataCache . Add ( String . Format ( CultureInfo . InvariantCulture , "{0}.{1}" , entityName , attributeName ) , attributeMetadata ) ;
255- _metadataLastValidatedAt = DateTime . Now ;
256- }
249+ _attributeMetadataCache . TryAdd ( String . Format ( CultureInfo . InvariantCulture , "{0}.{1}" , entityName , attributeName ) , attributeMetadata ) ;
250+ _metadataLastValidatedAt = DateTime . UtcNow ;
257251 }
258252 }
259253 }
@@ -333,10 +327,8 @@ public OptionSetMetadata GetGlobalOptionSetMetadata(string optionSetName)
333327 {
334328 if ( response . OptionSetMetadata is OptionSetMetadata && ( OptionSetMetadata ) response . OptionSetMetadata != null )
335329 {
336- lock ( _lockObject )
337- {
338- _globalOptionMetadataCache . Add ( optionSetName , ( OptionSetMetadata ) response . OptionSetMetadata ) ;
339- }
330+ _globalOptionMetadataCache . TryAdd ( optionSetName , ( OptionSetMetadata ) response . OptionSetMetadata ) ;
331+ TouchMetadataDate ( ) ;
340332 return _globalOptionMetadataCache [ optionSetName ] ;
341333 }
342334 }
@@ -348,17 +340,22 @@ public OptionSetMetadata GetGlobalOptionSetMetadata(string optionSetName)
348340 /// </summary>
349341 private void ValidateMetadata ( )
350342 {
351- if ( DateTime . Now . Subtract ( _metadataLastValidatedAt ) . TotalHours > 1 )
352- {
353- lock ( _lockObject )
354- {
355- _metadataLastValidatedAt = DateTime . Now ;
356- _attributeMetadataCache . Clear ( ) ;
357- _entityMetadataCache . Clear ( ) ;
358- _entityNameCache . Clear ( ) ;
359- _globalOptionMetadataCache . Clear ( ) ;
360- }
361- }
362- }
363- }
343+ if ( DateTime . UtcNow . Subtract ( _metadataLastValidatedAt ) . TotalHours > 1 )
344+ {
345+ TouchMetadataDate ( ) ;
346+ _attributeMetadataCache . Clear ( ) ;
347+ _entityMetadataCache . Clear ( ) ;
348+ _entityNameCache . Clear ( ) ;
349+ _globalOptionMetadataCache . Clear ( ) ;
350+ }
351+ }
352+
353+ private void TouchMetadataDate ( )
354+ {
355+ lock ( _lockObject )
356+ {
357+ _metadataLastValidatedAt = DateTime . UtcNow ;
358+ }
359+ }
360+ }
364361}
0 commit comments