views:

163

answers:

0

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.
    References Common and Oracle.DataAccess.
  • DataAccessLayer contains the high-level database stuff, such as connection management, threading, readers...
    References Common, Oracle.DataAccess and OracleAdapter
  • Several Wrapper assemblies, each of which wraps a package of database procedures (encapsulating database types, calling conventions and such). Automatically generated in advance.
    References Common and Oracle.DataAccess.
  • Several Module assemblies which contain application forms.
    References Common, DataAccessLayer and Wrapper.

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:

  1. Open Visual Studio
  2. Open the designer for a form in Module and close it.
  3. Rebuild the solution.
  4. 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 the OracleAdapter assembly does not use native DLLs, just Oracle.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. The Wrapper 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 instantiate OracleAdapter.
  • Originally, there was no OracleAdapter, and Oracle.DataAccess was referenced by both DataAccessLayer and Wrapper. 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!