SharpMap и Entity Framework: вызываемый элемент не поддерживается в динамической сборке

Я использую четкую карту внутри собственного компонента "виджет карты". Чтобы заполнить карту, я хочу использовать структуру сущностей, которая находится внутри отдельной DLL. Это прекрасно работает, если я создаю карту, а затем получаю данные.

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
}

Однако, если я сначала получу данные, а затем составлю карту, все пойдет не так:

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

результаты в

   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  

Какого черта здесь происходит? Зачем использовать структуру сущностей первым?

Чтобы исправить эту проблему, я добавил это в program.cs, чтобы сначала загрузить виджет.

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());
}

Однако мне это не нравится - это кажется довольно хрупким, и мне не нравится "кодирование по совпадению". Что я могу сделать, чтобы это исправить?

Замечания:

Я нашел это сообщение в блоге: http://elegantcode.com/2010/01/28/the-entity-framework-and-the-the-invoked-member-is-not-supported-in-a-dynamic-assembly-exception/ я добавил сборку домена в connectionString

Моя структура проекта такова:

Dashboard.exe

  • App.Config содержит строку подключения
  • Рекомендации SharpMap
  • Ссылки Domain.Dll
  • Содержит MapWidget

Domain.dll

  • Содержит DomainModel и Сервисы
  • Использует Entity Model для настойчивости
  • App.config содержит строку соединения, раздел конфигурации инфраструктуры сущностей и фабрику соединений инфраструктуры сущностей

Итак, мои вопросы:

  1. Почему это происходит?
  2. Что я могу сделать, чтобы остановить это? (Если нет, то есть ли лучшее место, чем Program.cs для хакерского кода)

Спасибо за чтение, пожалуйста, попросите уточнить, если я не был ясен.

2 ответа

Решение

У меня была очень похожая проблема, но я не использую Entity Framework (вместо этого я использую NHibernate), поэтому я понял, что это, в конце концов, может не быть проблемой прокси-объекта.

Мне также не нравится "кодирование по совпадению", но я предполагаю, что, позвонив new MapWidget()некоторая инициализация, связанная с GeoApi, выполняется внутри - поскольку GeoApi используется SharpMap для внутреннего использования.

В моем случае я не использовал карту напрямую, я просто вставлял некоторые геоданные в свою базу данных, используя NHibernate, и я получал точно такую ​​же трассировку стека, поэтому я подумал, что это может быть той же проблемой.

Как бы я ни ненавидел это, у меня было что-то вроде этого:

// 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

и это дало мне точное исключение, как у вас. После изменения на

// 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);

это работало просто отлично. В моем случае я использовал new Map() вместо new MapWidget() потому что это приложение winforms.

TLDR: воспринимайте это как хак, который выполняет инициализацию

Скорее всего, это связано с динамическими прокси, генерируемыми EF. Я не знаком с SharpMap, поэтому не могу прокомментировать, какой эффект имеет его инициализация перед EF, но вы должны быть в состоянии избежать исключения, отключив создание прокси:

context.Configuration.ProxyCreationEnabled = false;

Обратите внимание, что это отключит отложенную загрузку и отслеживание изменений, поэтому сначала внимательно прочитайте эту статью: http://msdn.microsoft.com/en-us/data/jj592886

Другие вопросы по тегам