private void InternalRefreshCompletedHandler(object sender, EventArgs eventArgs)
        {
            var refreshedModel = GetDatabaseModelIfDifferentCompatibleInstance(sender);

            if (refreshedModel == null)
            {
                return;
            }

            _dataDictionary     = refreshedModel._dataDictionary;
            _allProgramMetadata = refreshedModel._allProgramMetadata;
            _uniqueConstraintReferringReferenceConstraints = refreshedModel._uniqueConstraintReferringReferenceConstraints;
            _allSchemas = refreshedModel._allSchemas;
            _schemas    = refreshedModel._schemas;

            TraceLog.WriteLine($"Metadata for '{_connectionStringName}/{ConnectionIdentifier}' has been retrieved from the cache. ");

            lock (ActiveDataModelRefresh)
            {
                if (WaitingDataModelRefresh.TryGetValue(_connectionStringName, out List <RefreshModel> refreshModels))
                {
                    var modelIndex = refreshModels.FindIndex(m => m.DatabaseModel == this);
                    if (modelIndex != -1)
                    {
                        refreshModels[modelIndex].TaskCompletionSource.SetResult(_dataDictionary);
                        refreshModels.RemoveAt(modelIndex);
                    }
                }
            }

            _isRefreshing = false;
            RaiseEvent(RefreshCompleted);
        }
        private void BuildSupportLookups()
        {
            try
            {
                var functionMetadata = _dataDictionary.AllObjects.Values
                                       .OfType <IProgramCollection>()
                                       .SelectMany(o => o.Programs);

                _allProgramMetadata = FilterFunctionsWithUnavailableMetadata(functionMetadata)
                                      .Concat(_dataDictionary.NonSchemaFunctionMetadata.SelectMany(g => g))
                                      .ToLookup(m => m.Identifier);

                _uniqueConstraintReferringReferenceConstraints = BuildUniqueConstraintReferringReferenceConstraintLookup(_dataDictionary.AllObjects.Values);
            }
            catch (Exception e)
            {
                _dataDictionary = OracleDataDictionary.EmptyDictionary;
                TraceLog.WriteLine($"All function metadata or unique constraint referring reference constraint lookup initialization from cache failed: {e}");
            }
        }
        private void TryLoadSchemaObjectMetadataFromCache()
        {
            if (_cacheLoaded)
            {
                return;
            }

            if (CachedDataDictionaries.TryGetValue(_connectionStringName, out OracleDataDictionary dataDictionary))
            {
                _dataDictionary = dataDictionary;
                BuildSupportLookups();
            }
            else if (MetadataCache.TryLoadDatabaseModelCache(_connectionStringName, out Stream stream))
            {
                try
                {
                    RaiseEvent(RefreshStarted);
                    RaiseRefreshStatusChanged("Loading data dictionary metadata cache... ");
                    TraceLog.WriteLine($"Attempt to load metadata for '{_connectionStringName}/{ConnectionIdentifier}' from cache. ");
                    var stopwatch = Stopwatch.StartNew();
                    _dataDictionary = CachedDataDictionaries[_connectionStringName] = OracleDataDictionary.Deserialize(stream);
                    TraceLog.WriteLine($"Metadata for '{_connectionStringName}/{ConnectionIdentifier}' loaded from cache in {stopwatch.Elapsed}");
                    BuildSupportLookups();
                }
                catch (Exception e)
                {
                    TraceLog.WriteLine($"Oracle data dictionary cache deserialization failed: {e}");
                }
                finally
                {
                    stream.Dispose();
                    RaiseEvent(RefreshCompleted);
                }
            }

            _cacheLoaded = true;
        }
        public void GenerateCustomTypeAssembly(OracleDataDictionary dataDictionary)
        {
            if (_customTypeAssembly != null)
            {
                return;
            }

            TraceLog.WriteLine($"Custom object and collection types generation started. ");

            var stopwatch = Stopwatch.StartNew();

            var fileVersionAttribute     = CurrentAssembly.GetCustomAttribute <AssemblyFileVersionAttribute>();
            var targetFrameworkAttribute = CurrentAssembly.GetCustomAttribute <TargetFrameworkAttribute>();
            var companyAttribute         = CurrentAssembly.GetCustomAttribute <AssemblyCompanyAttribute>();
            var productAttribute         = CurrentAssembly.GetCustomAttribute <AssemblyProductAttribute>();

            var assemblyVersion             = CurrentAssembly.GetName().Version;
            var constructorStringParameters = new[] { typeof(string) };

            var customAttributeBuilders = new[]
            {
                new CustomAttributeBuilder(typeof(AssemblyTitleAttribute).GetConstructor(constructorStringParameters), GetParameterAsObjectArray(DynamicAssemblyNameBase)),
                new CustomAttributeBuilder(typeof(NeutralResourcesLanguageAttribute).GetConstructor(constructorStringParameters), GetParameterAsObjectArray(String.Empty)),
                new CustomAttributeBuilder(typeof(GuidAttribute).GetConstructor(constructorStringParameters), GetParameterAsObjectArray(Guid.NewGuid().ToString())),
                new CustomAttributeBuilder(typeof(AssemblyCompanyAttribute).GetConstructor(constructorStringParameters), GetParameterAsObjectArray(companyAttribute.Company)),
                new CustomAttributeBuilder(typeof(AssemblyProductAttribute).GetConstructor(constructorStringParameters), GetParameterAsObjectArray(productAttribute.Product)),
                new CustomAttributeBuilder(typeof(AssemblyDescriptionAttribute).GetConstructor(constructorStringParameters), GetParameterAsObjectArray("This assembly contains dynamically generated Oracle custom data types. ")),
                new CustomAttributeBuilder(typeof(AssemblyCopyrightAttribute).GetConstructor(constructorStringParameters), GetParameterAsObjectArray("Copyright © " + DateTime.UtcNow.Year)),
                new CustomAttributeBuilder(typeof(AssemblyFileVersionAttribute).GetConstructor(constructorStringParameters), GetParameterAsObjectArray(fileVersionAttribute.Version)),
                new CustomAttributeBuilder(typeof(AssemblyInformationalVersionAttribute).GetConstructor(constructorStringParameters), GetParameterAsObjectArray(fileVersionAttribute.Version)),                  // Adds Product Version
                new CustomAttributeBuilder(typeof(ComVisibleAttribute).GetConstructor(new[] { typeof(bool) }), GetParameterAsObjectArray(false)),
                new CustomAttributeBuilder(typeof(AssemblyConfigurationAttribute).GetConstructor(constructorStringParameters), GetParameterAsObjectArray(String.Empty)),
                new CustomAttributeBuilder(typeof(AssemblyTrademarkAttribute).GetConstructor(constructorStringParameters), GetParameterAsObjectArray(String.Empty)),
                new CustomAttributeBuilder(typeof(TargetFrameworkAttribute).GetConstructor(constructorStringParameters), GetParameterAsObjectArray(targetFrameworkAttribute.FrameworkName))
            };

            var assemblyName = new AssemblyName(_customTypeAssemblyName)
            {
                Version = assemblyVersion
            };
            var customTypeAssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave, _customTypeAssemblyFile.DirectoryName, true, customAttributeBuilders);

            customTypeAssemblyBuilder.DefineVersionInfoResource();             // Makes attributes readable by unmanaged environment like Windows Explorer.
            var customTypeModuleBuilder = customTypeAssemblyBuilder.DefineDynamicModule(_customTypeAssemblyName, _customTypeAssemblyFile.Name, true);

            var customTypes = new Dictionary <string, Type>();

            foreach (var objectType in dataDictionary.AllObjects.Values.OfType <OracleTypeObject>().Where(t => t.TypeCode != OracleTypeBase.TypeCodeXml))
            {
                CreateOracleObjectType(customTypeModuleBuilder, objectType, customTypes);
            }

            var objectTypeCount = customTypes.Count;

            foreach (var collectionType in dataDictionary.AllObjects.Values.OfType <OracleTypeCollection>())
            {
                CreateOracleCollectionType(customTypeModuleBuilder, collectionType, customTypes);
            }

            customTypeAssemblyBuilder.Save(_customTypeAssemblyFile.Name);

            //var mappingTableField = typeof(OracleUdt).GetField("s_mapUdtNameToMappingObj", BindingFlags.Static | BindingFlags.NonPublic);
            //mappingTableField.SetValue(null, mappingTable);

            stopwatch.Stop();

            var collectionTypeCount = customTypes.Count - objectTypeCount;

            TraceLog.WriteLine($"{objectTypeCount} Custom object types and {collectionTypeCount} collection types generated into {_customTypeAssemblyFile.Name} in {stopwatch.Elapsed}. ");
        }
        private bool RefreshSchemaObjectMetadata()
        {
            var lastRefresh = DateTime.Now;

            try
            {
                RefreshSchemas();

                var allObjects = _dataDictionaryMapper.BuildDataDictionary();

                var userPrograms    = _dataDictionaryMapper.GetUserFunctionMetadata().SelectMany(g => g).ToArray();
                var builtInPrograms = _dataDictionaryMapper.GetBuiltInFunctionMetadata().SelectMany(g => g).ToArray();
                _allProgramMetadata = builtInPrograms
                                      .Concat(userPrograms)
                                      .ToLookup(m => m.Identifier);

                var stopwatch = Stopwatch.StartNew();

                var nonSchemaBuiltInFunctionMetadata = new List <OracleProgramMetadata>();

                foreach (var programMetadata in builtInPrograms.Concat(userPrograms))
                {
                    if (String.IsNullOrEmpty(programMetadata.Identifier.Owner))
                    {
                        nonSchemaBuiltInFunctionMetadata.Add(programMetadata);
                        continue;
                    }

                    var packageIdentifier = OracleObjectIdentifier.Create(programMetadata.Identifier.Owner, programMetadata.Identifier.Package);
                    if (allObjects.TryGetFirstValue(out OracleSchemaObject schemaObject, packageIdentifier))
                    {
                        ((OraclePackage)schemaObject).Programs.Add(programMetadata);
                        programMetadata.Owner = schemaObject;
                    }
                    else
                    {
                        var programIdentifier = OracleObjectIdentifier.Create(programMetadata.Identifier.Owner, programMetadata.Identifier.Name);
                        if (allObjects.TryGetFirstValue(out schemaObject, programIdentifier))
                        {
                            ((OracleSchemaProgram)schemaObject).Metadata = programMetadata;
                            programMetadata.Owner = schemaObject;
                        }
                    }
                }

                OracleDataDictionaryMapper.WriteTrace(ConnectionString.Name, $"Function and procedure metadata schema object mapping finished in {stopwatch.Elapsed}. ");

                stopwatch.Reset();

                _uniqueConstraintReferringReferenceConstraints = BuildUniqueConstraintReferringReferenceConstraintLookup(allObjects.Values);

                var databaseLinks    = _dataDictionaryMapper.GetDatabaseLinks();
                var characterSets    = _dataDictionaryMapper.GetCharacterSets();
                var statisticsKeys   = SafeFetchDictionary(_dataDictionaryMapper.GetStatisticsKeys, "OracleDataDictionaryMapper.GetStatisticsKeys failed: ");
                var systemParameters = SafeFetchDictionary(_dataDictionaryMapper.GetSystemParameters, "OracleDataDictionaryMapper.GetSystemParameters failed: ");

                OracleDataDictionaryMapper.WriteTrace(ConnectionString.Name, $"Unique constraint, database link, character sets, statistics keys and system parameter mapping finished in {stopwatch.Elapsed}. ");

                _dataDictionary = new OracleDataDictionary(allObjects, databaseLinks, nonSchemaBuiltInFunctionMetadata, characterSets, statisticsKeys, systemParameters, lastRefresh);

                OracleDataDictionaryMapper.WriteTrace(ConnectionString.Name, "Data dictionary metadata cache has been initialized successfully. ");

                //_customTypeGenerator.GenerateCustomTypeAssembly(_dataDictionary);

                CachedDataDictionaries[_connectionStringName] = _dataDictionary;

                return(true);
            }
            catch (Exception e)
            {
                OracleDataDictionaryMapper.WriteTrace(ConnectionString.Name, $"Oracle data dictionary refresh failed: {e}");
                return(false);
            }
        }