I have the answer - but not the solution.
If we look at the code in GetModuleByDefinition - we need to focus on where something is inserted into a dictionary - the error is caused by an attempt to call a method on a object that is null.
955 Public Function GetModuleByDefinition(ByVal PortalId As Integer, ByVal FriendlyName As String) As ModuleInfo
956
957 ' format cache key
958 Dim key As String = String.format(DataCache.ModuleCacheKey, PortalId)
959
960 ' get module dictionary from cache
961 Dim modules As Dictionary(Of String, ModuleInfo) = TryCast(DataCache.GetPersistentCacheItem(key, GetType(Dictionary(Of String, ModuleInfo))), Dictionary(Of String, ModuleInfo))
962
963 If modules Is Nothing Then
964 ' set module caching settings
965 Dim timeOut As Int32 = DataCache.ModuleCacheTimeOut * Convert.ToInt32(Common.Globals.PerformanceSetting)
966
967 ' create new dictionary
968 modules = New Dictionary(Of String, ModuleInfo)
969
970 ' cache module dictionary
971 If timeOut > 0 Then
972 DataCache.SetCache(key, modules, TimeSpan.FromMinutes(timeOut), True)
973 End If
974 End If
975
976 ' declare return object
977 Dim objModule As ModuleInfo = Nothing
978
979 ' get specific module object from cache based on FriendlyName
980 If modules.ContainsKey(FriendlyName) Then
981 objModule = modules(FriendlyName)
982 End If
983
984 ' if module is not in cache
985 If objModule Is Nothing Then
986 ' get from database
987 Dim dr As IDataReader = DataProvider.Instance().GetModuleByDefinition(PortalId, FriendlyName)
988 Try
989 ' hydrate object
990 objModule = FillModuleInfo(dr)
991 Finally
992 ' close connection
993 If Not dr Is Nothing Then
994 dr.Close()
995 End If
996 End Try
997 ' add object to module cache dictionary
998 modules(FriendlyName) = objModule
999 End If
1000
1001 ' return module object
1002 Return objModule
1003 End Function
In line 998 an attempt is made to add objModule to modules. This is the only line of code in this method where the method is Dictionary'.Insert (the compiler converts the statement "module(FriendlyName) = objModule" to "modules.Insert(FriendlyName, objModule)".
If we look at the code an attempt is made to retrieve the Dictionary from the cache (line 961). If it is null a new one is created and added to the cache (lines 963 - 974) then an attempt is made to find the module in the Dictionary, and if it is not there add it (line 998). You would think at first glance that there is guarnateed to be Dictionary so why the null refernec exception.
However, we need to understand how the cache works.
- In line 961 we get a reference to a cached object.
- In line 963 we check if it is nothing - lets assume it isn't
- In line 998 we now attempt to reference it - but what if the cache has expired the object in the meantime - the reference will now be null.
So the issue happens in a memory intensive site - where the cache expires between line 963 and line 998 as ASP.NET determines it needs more memory.