如何防止EF4动态加载所有程序集
我们使用ClickOnce进行动态装配加载。 我最近在解决方案中为模型项目添加了EF4模型。
应用程序不能使用它的连接字符串的app.config文件,所以我使用EntityConnection创建ObjectContext。
但是,当您使用ClickOnce部署应用程序时,当您创建ObjectContext的实例时,应用程序逻辑可以正常工作,EF4会尝试动态加载所有关联的程序集以查找元数据。
这迫使clickonce下载clickonce DLL地图中的每一个程序集!
这是调用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)
我怎样才能防止EF4做到这一点?
谢谢!
在遵循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应用程序)。 这个库引用水晶报表的DLL,它现在会导致EF4抛出一个ReflectTypeLoadException,因为该机器没有安装水晶。
是的,这是没有*通配符和预生成的意见。
是否真的没有办法明确告诉EF4不要装载汇编(它真的不需要)? 否则,看起来我将不得不完全放弃EF4。
您应该在您的EF连接字符串中指定正确的程序集,而不是使用*
通配符。
上一篇: How to prevent EF4 from dynamically loading all assemblies