Как предотвратить динамическую загрузку всех сборок EF4 - PullRequest
2 голосов
/ 02 августа 2011

Мы используем ClickOnce с динамической загрузкой сборки.Недавно я добавил модель EF4 в проект «Модель» в решении.

Приложение не должно использовать файл app.config для своей строки подключения, поэтому я создаю ObjectContext с использованием EntityConnection.

Логика приложения работает отлично, однако, когда вы создаете экземпляр ObjectContext при развертывании приложения с использованием ClickOnce, EF4 пытается динамически загрузить все связанные сборки, чтобы найти метаданные.

Это заставляет clickonceзагрузить каждую сборку на карте clickonce dll!

Вот трассировка стека при вызове ctor ObjectContext:

   at System.AppDomain.OnAssemblyResolveEvent(RuntimeAssembly assembly, String assemblyFullName)
   at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection, Boolean suppressSecurityChecks)
   at System.Reflection.Assembly.Load(AssemblyName assemblyRef)
   at System.Data.Metadata.Edm.MetadataAssemblyHelper.SafeLoadReferencedAssembly(AssemblyName assemblyName)
   at System.Data.Metadata.Edm.MetadataAssemblyHelper.<GetNonSystemReferencedAssemblies>d__0.MoveNext()
   at System.Data.Metadata.Edm.DefaultAssemblyResolver.GetAllDiscoverableAssemblies()
   at System.Data.Metadata.Edm.DefaultAssemblyResolver.GetWildcardAssemblies()
   at System.Data.Metadata.Edm.MetadataArtifactLoaderCompositeResource.LoadResources(String assemblyName, String resourceName, ICollection`1 uriRegistry, MetadataArtifactAssemblyResolver resolver)
   at System.Data.Metadata.Edm.MetadataArtifactLoaderCompositeResource.CreateResourceLoader(String path, ExtensionCheck extensionCheck, String validExtension, ICollection`1 uriRegistry, MetadataArtifactAssemblyResolver resolver)
   at System.Data.Metadata.Edm.MetadataArtifactLoader.Create(String path, ExtensionCheck extensionCheck, String validExtension, ICollection`1 uriRegistry, MetadataArtifactAssemblyResolver resolver)
   at System.Data.Metadata.Edm.MetadataCache.SplitPaths(String paths)
   at System.Data.Common.Utils.Memoizer`2.<>c__DisplayClass2.<Evaluate>b__0()
   at System.Data.Common.Utils.Memoizer`2.Result.GetValue()
   at System.Data.Common.Utils.Memoizer`2.Evaluate(TArg arg)
   at System.Data.EntityClient.EntityConnection.GetMetadataWorkspace(Boolean initializeAllCollections)
   at System.Data.Objects.ObjectContext.RetrieveMetadataWorkspaceFromConnection()
   at System.Data.Objects.ObjectContext..ctor(EntityConnection connection, Boolean isConnectionConstructor)

Как я могу предотвратить это в EF4?

Спасибо!


После следования совету Крэйга я теперь могу создать экземпляр ObjectContext, не пытаясь загрузить все сборки.

Однако теперь он пытаетсязагрузить все сборки при выполнении запроса.Пожалуйста, смотрите трассировку стека ниже:

   at System.AppDomain.OnAssemblyResolveEvent(RuntimeAssembly assembly, String assemblyFullName)
   at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection, Boolean suppressSecurityChecks)
   at System.Reflection.Assembly.Load(AssemblyName assemblyRef)
   at System.Data.Metadata.Edm.MetadataAssemblyHelper.SafeLoadReferencedAssembly(AssemblyName assemblyName)
   at System.Data.Metadata.Edm.MetadataAssemblyHelper.<GetNonSystemReferencedAssemblies>d__0.MoveNext()
   at System.Data.Metadata.Edm.ObjectItemCollection.ImplicitLoadViewsFromAllReferencedAssemblies(Assembly assembly)
   at System.Data.Mapping.StorageMappingItemCollection.ViewDictionary.SerializedCollectViewsFromReferencedAssemblies(MetadataWorkspace workspace, Dictionary`2 extentMappingViews)
   at System.Data.Mapping.StorageMappingItemCollection.ViewDictionary.SerializedGetGeneratedViews(EntityContainer container)
   at System.Data.Common.Utils.Memoizer`2.<>c__DisplayClass2.<Evaluate>b__0()
   at System.Data.Common.Utils.Memoizer`2.Result.GetValue()
   at System.Data.Common.Utils.Memoizer`2.Evaluate(TArg arg)
   at System.Data.Mapping.StorageMappingItemCollection.ViewDictionary.GetGeneratedView(EntitySetBase extent, MetadataWorkspace workspace, StorageMappingItemCollection storageMappingItemCollection)
   at System.Data.Metadata.Edm.MetadataWorkspace.GetGeneratedView(EntitySetBase extent)
   at System.Data.Query.PlanCompiler.PreProcessor.ExpandView(Node node, ScanTableOp scanTableOp, IsOfOp& typeFilter)
   at System.Data.Query.PlanCompiler.PreProcessor.ProcessScanTable(Node scanTableNode, ScanTableOp scanTableOp, IsOfOp& typeFilter)
   at System.Data.Query.PlanCompiler.PreProcessor.Visit(ScanTableOp op, Node n)
   at System.Data.Query.InternalTrees.ScanTableOp.Accept[TResultType](BasicOpVisitorOfT`1 v, Node n)
   at System.Data.Query.InternalTrees.BasicOpVisitorOfT`1.VisitNode(Node n)
   at System.Data.Query.PlanCompiler.SubqueryTrackingVisitor.VisitChildren(Node n)
   at System.Data.Query.PlanCompiler.SubqueryTrackingVisitor.VisitRelOpDefault(RelOp op, Node n)
   at System.Data.Query.PlanCompiler.PreProcessor.Visit(ProjectOp op, Node n)
   at System.Data.Query.InternalTrees.ProjectOp.Accept[TResultType](BasicOpVisitorOfT`1 v, Node n)
   at System.Data.Query.InternalTrees.BasicOpVisitorOfT`1.VisitNode(Node n)
   at System.Data.Query.PlanCompiler.SubqueryTrackingVisitor.VisitChildren(Node n)
   at System.Data.Query.InternalTrees.BasicOpVisitorOfNode.VisitDefault(Node n)
   at System.Data.Query.InternalTrees.BasicOpVisitorOfNode.VisitPhysicalOpDefault(PhysicalOp op, Node n)
   at System.Data.Query.InternalTrees.BasicOpVisitorOfT`1.Visit(PhysicalProjectOp op, Node n)
   at System.Data.Query.InternalTrees.PhysicalProjectOp.Accept[TResultType](BasicOpVisitorOfT`1 v, Node n)
   at System.Data.Query.InternalTrees.BasicOpVisitorOfT`1.VisitNode(Node n)
   at System.Data.Query.PlanCompiler.PreProcessor.Process()
   at System.Data.Query.PlanCompiler.PreProcessor.Process(PlanCompiler planCompilerState, StructuredTypeInfo& typeInfo)
   at System.Data.Query.PlanCompiler.PlanCompiler.Compile(List`1& providerCommands, ColumnMap& resultColumnMap, Int32& columnCount, Set`1& entitySets)
   at System.Data.EntityClient.EntityCommandDefinition..ctor(DbProviderFactory storeProviderFactory, DbCommandTree commandTree)
   at System.Data.EntityClient.EntityProviderServices.CreateCommandDefinition(DbProviderFactory storeProviderFactory, DbCommandTree commandTree)
   at System.Data.EntityClient.EntityProviderServices.CreateDbCommandDefinition(DbProviderManifest providerManifest, DbCommandTree commandTree)
   at System.Data.Common.DbProviderServices.CreateCommandDefinition(DbCommandTree commandTree)
   at System.Data.Objects.Internal.ObjectQueryExecutionPlan.Prepare(ObjectContext context, DbQueryCommandTree tree, Type elementType, MergeOption mergeOption, Span span, ReadOnlyCollection`1 compiledQueryParameters)
   at System.Data.Objects.EntitySqlQueryState.GetExecutionPlan(Nullable`1 forMergeOption)
   at System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
   at System.Data.Objects.ObjectQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)

Буду признателен за любую дополнительную помощь!Спасибо.


Ну, я думаю, что если используется *, он должен сначала проверить текущую сборку.99% времени это будет правильно.Загрузка каждой сборки, а затем только проверка текущей сборки кажется мне ошибкой.

Необязательно использовать отражение, чтобы попытаться загрузить каждую DLL.

Хотя у меня все еще есть проблемы с этим.Библиотека моделей, которая содержит всю бизнес-логику для компании, используется где-то еще (а не в оригинальном приложении ClickOnce, упомянутом выше).Эта библиотека ссылается на библиотеки DLL Crystal Report, которые теперь заставляют EF4 генерировать исключение ReflectTypeLoadException, потому что на этом компьютере не установлена ​​программа Crystal.

И да, это без подстановочного знака * и с предварительно сгенерированными представлениями.

Неужели ДЕЙСТВИТЕЛЬНО нет способа явно сказать EF4 НЕ ЗАГРУЗИТЬ СБОРКИ (это действительно не нужно)?В противном случае, похоже, мне придется полностью отказаться от EF4.

1 Ответ

2 голосов
/ 02 августа 2011

Вы должны указать правильную сборку в строке подключения EF вместо использования подстановочного знака *.

...