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 содержит строку соединения, раздел конфигурации инфраструктуры сущностей и фабрику соединений инфраструктуры сущностей
Итак, мои вопросы:
- Почему это происходит?
- Что я могу сделать, чтобы остановить это? (Если нет, то есть ли лучшее место, чем 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