SharpMap and Entity Framework: The invoked member is not supported in a dynamic assembly

c# entity-framework sharpmap

Question

I am using sharp map inside a custom "map widget" component. To populate the map, I want to use the entity framework, which is inside a seperate DLL. This works fine if I create a map, and then get the data.

public void loadMap() {
     var map = new MapWidget(); // Create a new widget which internally uses SharpMap
     map.AddCountriesLayer(); // Load the map background from .shp file
     var data = new IPService.GetPointsForMap(); // Gets IP address from entity framework, inside "domain.dll"
     map.AddDots(data); // Add dots
}

However, if I get the data first, and then make the map, things break:

public void loadMap() {
     var data = new IPService.GetPointsForMap(); // Accessing entity framework before sharpmap
     var map = new MapWidget();
     map.AddCountriesLayer();
     map.AddDots(data);
}

results in

   System.NotSupportedException "The invoked member is not supported in a dynamic assembly."
   at System.Reflection.Emit.InternalAssemblyBuilder.GetExportedTypes()     
   at GeoAPI.GeometryServiceProvider.ReflectInstance()     
   at GeoAPI.GeometryServiceProvider.get_Instance()     
   at SharpMap.Data.Providers.ShapeFile.set_SRID(Int32 value) in C:\dev\DLLs\SharpMap Source\Trunk\SharpMap\Data\Providers\ShapeFile.cs:line 859     
   at SharpMap.Data.Providers.ShapeFile.ParseProjection() in C:\dev\DLLs\SharpMap Source\Trunk\SharpMap\Data\Providers\ShapeFile.cs:line 978     
   at SharpMap.Data.Providers.ShapeFile..ctor(String filename, Boolean fileBasedIndex) in C:\dev\DLLs\SharpMap Source\Trunk\SharpMap\Data\Providers\ShapeFile.cs:line 302     
   at Dashboard.Widgets.MapWidget.AddCountriesLayer() in c:\dev\Dashboard\v1\Dashboard\Classes\Widgets\Generic\MapWidget.cs:line 86  

What the heck is going on here? Why would using the entity framework first break it?

To fix this issue, I added this to the program.cs, to force the widget to be loaded first.

static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    // Hack to force SharpMap to register before entity framework
    var widget = new Widgets.MapWidget();
    widget.Update();

    Application.Run(new DashboardForm());
}

However, I don't like it - it seems pretty fragile and I don't like "coding by coincidence". Is there anything I can do to fix it?

Note:

I found this blog post: http://elegantcode.com/2010/01/28/the-entity-framework-and-the-the-invoked-member-is-not-supported-in-a-dynamic-assembly-exception/ I added the domain assembly to the connectionString

My project structure is this:

Dashboard.exe

  • App.Config contains connectionstring
  • References SharpMap
  • References Domain.Dll
  • Contains MapWidget

Domain.dll

  • Contains DomainModel and Services
  • Uses Entity Model for persistance
  • App.config contains connectionstring, entity framework config section and entity framework connection factory

So my questions are:

  1. Why is it happening?
  2. What can I do to stop it? (If not, is there a better place then Program.cs for the hacky code)

Thanks for reading, please ask me to clarify if I haven't been clear.

1
3
3/10/2013 12:10:15 AM

Accepted Answer

I had a very similar problem, but I'm not using Entity Framework (I'm using NHibernate instead), so, I've figured out that this may not be a proxy-object problem after all.

I also dislike "coding by coincidence", but I assume that by calling new MapWidget(), some initialization related to GeoApi is performed internally - as GeoApi is used by SharpMap internally.

In my case, I was not using the map directly, I was simply inserting some geo data in my database using NHibernate and I was getting exact same stack trace, so I figured that might be the same problem.

As much as I hate it, I had something like this:

// my object to be persisted using NHibernate
var myObj = new MyObj();

// add polygon of type GeoAPI.Geometries.IGeometry
myObj.CoveredArea = myGeoFactory.CreatePolygonArea(/* ... */);

// use NHibernate to save my obj
sessioNScope.Save(myObj); // <- throws NotSupportedException here

and it gave me exact exception as you had. After changing it to

// Ignore this line: hack to initialize GeoApi
new Map(); 

// my object to be persisted using NHibernate
var myObj = new MyObj();

// add polygon of type GeoAPI.Geometries.IGeometry
myObj.CoveredArea = myGeoFactory.CreatePolygonArea(/* ... */);

// use NHibernate to save my obj
sessioNScope.Save(myObj);

it worked just fine. In my case I used new Map() instead of new MapWidget() because it is a application.

TLDR: think of it as an hack, which performs initialization

2
11/12/2013 5:06:06 PM

Popular Answer

This is most likely due to the dynamic proxies generated by EF. I'm not familiar with SharpMap, so I can't comment on what effect does it have to initialize it before EF, but you should be able to avoid the exception by disabling proxy creation:

context.Configuration.ProxyCreationEnabled = false;

Note that this will disable lazy loading and change tracking, so first read this article carefully: http://msdn.microsoft.com/en-us/data/jj592886



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow