C# 调用AppDomain.CurrentDomain.AssemblyResolve时,ResolveEventArgs.RequestingAssembly为null

C# 调用AppDomain.CurrentDomain.AssemblyResolve时,ResolveEventArgs.RequestingAssembly为null,c#,sql-server-2008-r2,sql-server-2012,entity-framework-6,C#,Sql Server 2008 R2,Sql Server 2012,Entity Framework 6,作为持续集成工作的一部分,我们创建了一个自定义部署应用程序,用于处理EntityFramework6.0代码优先数据库迁移。我们将目标DLL与当前部署的DLL进行比较,以确定迁移路径是向上还是向下。为了确保加载数据上下文DLL的正确版本,我们正在侦听AppDomain.CurrentDomain.AssemblyResolve(请参阅:) 我们删除了TableAttribute,当它在SQL Server 2008 R2上仍然失败时,该错误在SQL Server 2012上变得可重现。我们使用的

作为持续集成工作的一部分,我们创建了一个自定义部署应用程序,用于处理EntityFramework6.0代码优先数据库迁移。我们将目标DLL与当前部署的DLL进行比较,以确定迁移路径是向上还是向下。为了确保加载数据上下文DLL的正确版本,我们正在侦听AppDomain.CurrentDomain.AssemblyResolve(请参阅:)


我们删除了
TableAttribute
,当它在SQL Server 2008 R2上仍然失败时,该错误在SQL Server 2012上变得可重现。

我们使用的粘合绷带是在确定目标和部署的DLL之后以及数据库初始化之前,注销我们的
ResolveDependentAssembly
事件。在我们目前的情况下,这将很好地工作,因为我们只在一个环境中部署数据上下文

我们的长期解决方案是为目标和每个部署创建单独的应用程序域

using System;
using System.Collections.Concurrent;
using System.IO;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;

public enum MigrationsSource
{
    Target = 1,
    Deployed= 2
}

public class AssemblyLoader
{
    private readonly ConcurrentDictionary<string, MigrationsSource> m_Sources = new ConcurrentDictionary<string, MigrationsSource>();
    private string m_DeployedPath;
    private string m_TargetPath;

    public AssemblyLoader()
    {
        AppDomain.CurrentDomain.AssemblyResolve += ResolveDependentAssembly;
    }

    ~AssemblyLoader()
    {
        AppDomain.CurrentDomain.AssemblyResolve -= ResolveDependentAssembly;
    }

    private Assembly ResolveDependentAssembly(object sender, ResolveEventArgs args)
    {
        MigrationsSource source;

        if (m_Sources.TryGetValue(BuildAssemblyId(args.RequestingAssembly), out source))
        {
            var assemblyName = new AssemblyName(args.Name);

            string targetPath = Path.Combine(
                source == MigrationsSource.Deployed ? m_DeployedPath : m_TargetPath, string.Format("{0}.dll", assemblyName.Name));

            assemblyName.CodeBase = targetPath;

            //We have to use LoadFile here, otherwise we won't load a differing
            //version, regardless of the codebase because only LoadFile
            //will actually load a *new* assembly if it's at a different path
            //See: http://msdn.microsoft.com/en-us/library/b61s44e8(v=vs.110).aspx
            var dependentAssembly = Assembly.LoadFile(assemblyName.CodeBase);
            m_Sources.TryAdd(BuildAssemblyId(dependentAssembly), source);

            return dependentAssembly;
        }

        return null;
    }

    private string BuildAssemblyId(Assembly assembly)
    {
        return
            Convert.ToBase64String(
            HashAlgorithm.Create("SHA1")
                .ComputeHash(UTF8Encoding.UTF8.GetBytes(
                    string.Format("{0}|{1}", assembly.FullName, assembly.Location))));
    }
}
Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.
   at EntityFramework.AssemblyLoader.BuildAssemblyId(Assembly assembly) in c:\EntityFramework\AssemblyLoader.cs:line 103
   at EntityFramework.AssemblyLoader.ResolveDependentAssembly(Object sender, ResolveEventArgs args) in c:\EntityFramework\AssemblyLoader.cs:line 42
   at System.AppDomain.OnAssemblyResolveEvent(RuntimeAssembly assembly, String assemblyFullName)
   at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMarkHandle stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName, ObjectHandleOnStack type)
   at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName)
   at System.RuntimeType.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark)
   at System.Type.GetType(String typeName, Boolean throwOnError)
   at System.Data.Entity.Infrastructure.DependencyResolution.ClrTypeAnnotationSerializer.Deserialize(String name, String value)
   at System.Data.Entity.Core.SchemaObjectModel.SchemaElement.CreateMetadataPropertyFromXmlAttribute(String xmlNamespaceUri, String attributeName, String value)
   at System.Data.Entity.Core.SchemaObjectModel.SchemaElement.AddOtherContent(XmlReader reader)
   at System.Data.Entity.Core.SchemaObjectModel.SchemaElement.ParseAttribute(XmlReader reader)
   at System.Data.Entity.Core.SchemaObjectModel.SchemaElement.Parse(XmlReader reader)
   at System.Data.Entity.Core.SchemaObjectModel.Schema.HandleEntityTypeElement(XmlReader reader)
   at System.Data.Entity.Core.SchemaObjectModel.Schema.HandleElement(XmlReader reader)
   at System.Data.Entity.Core.SchemaObjectModel.SchemaElement.ParseElement(XmlReader reader)
   at System.Data.Entity.Core.SchemaObjectModel.SchemaElement.Parse(XmlReader reader)
   at System.Data.Entity.Core.SchemaObjectModel.Schema.HandleTopLevelSchemaElement(XmlReader reader)
   at System.Data.Entity.Core.SchemaObjectModel.Schema.InternalParse(XmlReader sourceReader, String sourceLocation)
   at System.Data.Entity.Core.SchemaObjectModel.Schema.Parse(XmlReader sourceReader, String sourceLocation)
   at System.Data.Entity.Core.SchemaObjectModel.SchemaManager.ParseAndValidate(IEnumerable`1 xmlReaders, IEnumerable`1 sourceFilePaths, SchemaDataModelOption dataModel, AttributeValueNotification providerNotification, AttributeValueNotification providerManifestTokenNotification, ProviderManifestNeeded providerManifestNeeded, IList`1& schemaCollection)
   at System.Data.Entity.Core.SchemaObjectModel.SchemaManager.ParseAndValidate(IEnumerable`1 xmlReaders, IEnumerable`1 sourceFilePaths, SchemaDataModelOption dataModel, DbProviderManifest providerManifest, IList`1& schemaCollection)
   at System.Data.Entity.Core.Metadata.Edm.EdmItemCollection.LoadItems(IEnumerable`1 xmlReaders, IEnumerable`1 sourceFilePaths, SchemaDataModelOption dataModelOption, DbProviderManifest providerManifest, ItemCollection itemCollection, Boolean throwOnError)
   at System.Data.Entity.Core.Metadata.Edm.EdmItemCollection.Init(IEnumerable`1 xmlReaders, IEnumerable`1 filePaths, Boolean throwOnError)
   at System.Data.Entity.Core.Metadata.Edm.EdmItemCollection..ctor(IEnumerable`1 xmlReaders)
   at System.Data.Entity.Utilities.XDocumentExtensions.GetStorageMappingItemCollection(XDocument model, DbProviderInfo&providerInfo)
   at System.Data.Entity.Migrations.Infrastructure.EdmModelDiffer.Diff(XDocument sourceModel, XDocument targetModel, Lazy`1 modificationCommandTreeGenerator, MigrationSqlGenerator migrationSqlGenerator, String sourceModelVersion, String targetModelVersion)
   at System.Data.Entity.Migrations.DbMigrator.IsModelOutOfDate(XDocument model, DbMigration lastMigration)
   at System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
   at System.Data.Entity.Migrations.DbMigrator.UpdateInternal(String targetMigration)
   at System.Data.Entity.Migrations.DbMigrator.<>c__DisplayClassc.<Update>b__b()
   at System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists(Action mustSucceedToKeepDatabase)
   at System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration)
   at System.Data.Entity.Internal.DatabaseCreator.CreateDatabase(InternalContext internalContext, Func`3 createMigrator, ObjectContext objectContext)
   at System.Data.Entity.Internal.InternalContext.CreateDatabase(ObjectContext objectContext, DatabaseExistenceState existenceState)
   at System.Data.Entity.Database.Create(DatabaseExistenceState existenceState)
   at System.Data.Entity.CreateDatabaseIfNotExists`1.InitializeDatabase(TContext context)
   at System.Data.Entity.Internal.InternalContext.<>c__DisplayClassf`1.<CreateInitializationAction>b__e()
   at System.Data.Entity.Internal.InternalContext.PerformInitializationAction(Action action)
   at System.Data.Entity.Internal.InternalContext.PerformDatabaseInitialization()
   at System.Data.Entity.Internal.LazyInternalContext.<InitializeDatabase>b__4(InternalContext c)
   at System.Data.Entity.Internal.RetryAction`1.PerformAction(TInput input)
   at System.Data.Entity.Internal.LazyInternalContext.InitializeDatabaseAction(Action`1 action)
   at System.Data.Entity.Internal.LazyInternalContext.InitializeDatabase()
   at EntityFramework.DbDeploymentManager.HandleDatabaseInitialization(DatabaseEndpoint endpoint) in c:\EntityFramework\DbDeploymentManager.cs:line 185
   at EntityFramework.DbDeploymentManager.Deploy() in c:\EntityFramework\DbDeploymentManager.cs:line 67
   at EntityFramework.Deployer.Program.Main(String[] args) in c:\EntityFramework.Deployer\Program.cs:line 23
[Table("dbo.tblCustomer")]
public class Customer
{
    public Guid Id { get; set; }
    public string Name { get; set; }
}