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.Common
contains data access interfaces (among other stuff) No references.OracleAdapter
contains Oracle-specific implementations of the data access interfaces.
ReferencesCommon
andOracle.DataAccess
.DataAccessLayer
contains the high-level database stuff, such as connection management, threading, readers...
ReferencesCommon
,Oracle.DataAccess
andOracleAdapter
- Several
Wrapper
assemblies, each of which wraps a package of database procedures (encapsulating database types, calling conventions and such). Automatically generated in advance.
ReferencesCommon
andOracle.DataAccess
. - Several
Module
assemblies which contain application forms.
ReferencesCommon
,DataAccessLayer
andWrapper
.
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
Module
and 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
EntryPointNotFoundException
occurs 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 theOracleAdapter
assembly 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
Form
a second time, i.e.Local Settings\Application Data\Microsoft\VisualStudio\8.0\ProjectAssemblies
contains two uniquely named subdirectories per assembly - one with the results of the first build, one with those of the second. TheWrapper
assembly, 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,
DataAccessLayer
is hard-coded to instantiateOracleAdapter
. - Originally, there was no
OracleAdapter
, andOracle.DataAccess
was referenced by bothDataAccessLayer
andWrapper
. Back then, everything worked fine.
The Questions
- Why does this
EntryPointNotFoundException
appear? - 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!