如何防止 EF4 动态加载所有程序集

发布于 2024-11-27 15:32:36 字数 8337 浏览 1 评论 0原文

我们使用 ClickOnce 进行动态程序集加载。我最近将 EF4 模型添加到解决方案中的“模型”项目中。

应用程序不得使用 app.config 文件作为其连接字符串,因此我使用 EntityConnection 创建 ObjectContext。

应用程序逻辑工作得很好,但是,当您在使用 ClickOnce 部署应用程序时创建 ObjectContext 实例时,EF4 会尝试动态加载所有关联的程序集以查找元数据。

这会强制 clickonce 下载 clickonce dll 映射中的每个程序集!

以下是调用 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)

How can I Prevent EF4 do this?

谢谢!


遵循 Craig 的建议后,我现在可以创建 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 应用程序)。该库引用 crystal 报表的 DLL,现在导致 EF4 抛出 ReflectTypeLoadException,因为该计算机没有安装 crystal。

是的,这没有 * 通配符,并且带有预先生成的视图。

真的没有办法明确告诉 EF4 不要加载程序集(它真的不需要)吗?否则看来我将不得不完全放弃 EF4。

We use ClickOnce with dynamic assembly loading. I recently added an EF4 model to a "Model" project within the solution.

The application must not use the app.config file for it's connection string, so I create the ObjectContext using an EntityConnection.

The application logic works perfectly, however, when you create an instance of the ObjectContext when the application is deployed using ClickOnce, EF4 tries to dynamically load all of the associated assemblies to find the metadata.

This forces clickonce to download every single assembly in the clickonce dll map!

Here is the stack trace when calling the ObjectContext ctor:

   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)

How can I prevent EF4 from doing this?

Thanks!


After following Craig's advice I am now able to create an instance of the ObjectContext without it trying to load all of the assemblies.

However, it now tries to load all of the assemblies when a query is run. Please see stack trace below:

   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)

I would appreciate any further assistance!
Thanks.


Well I think that if the * is used, it should first check the current assembly. 99% of the time that would be correct. Loading every single assembly and then only checking the current assembly seems like a bug to me.

It should be optional for it to use reflection to attempt to load every single dll.

I am still having issues with this though. The model library which contains all the business logic for the company, is being used elsewhere (not the original ClickOnce application mentioned above). This library references crystal report's DLLs which now causes EF4 to throw a ReflectTypeLoadException because that machine does not have crystal installed.

And yes, this is without the * wildcard and with pre-generated views.

Is there REALLY no way to explicitly tell EF4 NOT TO LOAD ASSEMBLIES (it really doesn't need to)? Otherwise it looks like I am going to have to abandon EF4 completely.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

一个人的旅程 2024-12-04 15:32:36

您应该在 EF 连接字符串中指定正确的程序集,而不是使用* 通配符。

You should specify the correct assembly in your EF connection string instead of using the * wildcard.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文