I did some refactoring of an application framework, and now the form designer behaves in a weird way - after a rebuild, it crashes with a EntryPointNotFoundException until Visual Studio is started again.
Background
The framework consists of several projects, all in one solution. The projects have several dependencies between each other, and there is an external dependency to the ADO.NET data provider for Oracle (Oracle.DataAccess). It also includes a proprietary data access layer that is active at design time.
The current architecture is this:
Oracle.DataAccess(external, loaded via global assembly cache)
Relies on non-.NET libraries installed as part of Oracle Client.Commoncontains data access interfaces (among other stuff) No references.OracleAdaptercontains Oracle-specific implementations of the data access interfaces.
ReferencesCommonandOracle.DataAccess.DataAccessLayercontains the high-level database stuff, such as connection management, threading, readers...
ReferencesCommon,Oracle.DataAccessandOracleAdapter- Several
Wrapperassemblies, each of which wraps a package of database procedures (encapsulating database types, calling conventions and such). Automatically generated in advance.
ReferencesCommonandOracle.DataAccess. - Several
Moduleassemblies which contain application forms.
ReferencesCommon,DataAccessLayerandWrapper.
For simplicity, let's pretend there is just one StoredProcedureWrapper and Module assembly each.
The Problem
As mentioned above, the designer no longer works after rebuilding. Here are the steps:
- Open Visual Studio
- Open the designer for a form in
Moduleand close it. - Rebuild the solution.
- Open the form again.
The result is an error message "Entry point was not found". Our log file includes this stack trace (stripped off full namespaces and debug info):
System.EntryPointNotFoundException: Entry point was not found.
at Common.DataAccess.IDatabaseCommand.get_Connection()
at DataAccessLayer.StoredProcedureBase.ExecuteInternal()
at DataAccessLayer.StoredProcedureBase.ExecuteSync()
at Tools.SystemConfiguration.GetParamAsString(String paramSpecKey)
at Components.Format.DateTimeFormats.GetFormatFromConfig(String formatName)
When Visual Studio and the designer are re-opened, everything works fine again - that is, until you rebuild the solution.
Some Notes
- A Google search indicates that
EntryPointNotFoundExceptionoccurs exclusively when dealing with native C/C++ DLLs, not .NET assemblies. The framework, however, exclusively references .NET assemblies. - The exception seems to occur at
IDatabaseCommand.get_Connection, which does not refer to an implementation. The implementation of this interface in theOracleAdapterassembly does not use native DLLs, justOracle.DataAccess. - I verified that the code that was just compiled is indeed used at the time of the crash.
- Furthermore, Visual Studio caches the compiled assemblies for all the projects referenced directly or transitively by
Forma second time, i.e.Local Settings\Application Data\Microsoft\VisualStudio\8.0\ProjectAssembliescontains two uniquely named subdirectories per assembly - one with the results of the first build, one with those of the second. TheWrapperassembly, though, is not cached a second time (due to it being precompiled) - The classes are being re-used: in the second design time environment, static members retain their values from the first one.
- Reflection is not used at all here - while I hunt down this issue,
DataAccessLayeris hard-coded to instantiateOracleAdapter. - Originally, there was no
OracleAdapter, andOracle.DataAccesswas referenced by bothDataAccessLayerandWrapper. Back then, everything worked fine.
The Questions
- Why does this
EntryPointNotFoundExceptionappear? - Why did it not appear before the refactoring?
- What can I do to solve this?
- Is it possible to be notified when a designer is closed and/or a rebuild takes place, so that I may force my framework to re-initialize?
Any pointers are much appreciated!