ResolveEventArgs.Метода имеет значение null, когда домен приложения.CurrentDomain.AssemblyResolve называется
в рамках наших непрерывных усилий по интеграции мы создали пользовательское приложение развертывания для обработки миграции первой базы данных кода Entity Framework 6.0. Мы берем наши целевые библиотеки DLL и сравниваем их с развернутыми библиотеками DLL, чтобы определить путь миграции вверх или вниз. Чтобы убедиться, что мы загружаем правильную версию DLL контекста данных, мы слушаем AppDomain.CurrentDomain.AssemblyResolve (см.: Загрузка Зависимых Сборки Вручную).
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))));
}
}
это прекрасно работает при развертывании простой контекст данных (одна таблица засеянный одной строке) на сервер под управлением SQL Server 2012 С (под управлением Windows Server 2012), но возникает следующая ошибка при развертывании той же простой контекст данных на сервере SQL сервер 2008 R2 (под управлением Windows Server 2008 стандартный):
Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.
at EntityFramework.AssemblyLoader.BuildAssemblyId(Assembly assembly) in c:EntityFrameworkAssemblyLoader.cs:line 103
at EntityFramework.AssemblyLoader.ResolveDependentAssembly(Object sender, ResolveEventArgs args) in c:EntityFrameworkAssemblyLoader.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:EntityFrameworkDbDeploymentManager.cs:line 185
at EntityFramework.DbDeploymentManager.Deploy() in c:EntityFrameworkDbDeploymentManager.cs:line 67
at EntityFramework.Deployer.Program.Main(String[] args) in c:EntityFramework.DeployerProgram.cs:line 23
некоторые выходные данные журнала показали, что BuildAssemblyId
устраивает NullReferenceException
потому что args.RequestingAssembly
вот быть переданным вnull
. Значение в args.Name
- это имя библиотеки DLL, содержащей наш контекст данных. Это происходит между созданием контекста и заполнением данных по мере создания таблицы, но пустым.
приложение было первоначально запущено на каждой машине независимо. Мы исключили несоответствие .NET Framework, обновив каждую машину до .NET 4.5.1. Кроме того, мы запустили приложение развертывания на той же машине; мы использовали машину, на которой был установлен SQL Server 2012. Наконец, приложение развертывания и простой контекст данных ссылаются на одну и ту же версию EntityFramework.
редактировать
было высказано предположение, что атрибут объекта таблицы может быть корнем проблемы.
[Table("dbo.tblCustomer")]
public class Customer
{
public Guid Id { get; set; }
public string Name { get; set; }
}
мы удалены TableAttribute
и пока он все еще не удалось на SQL Server 2008 R2 ошибка стала воспроизводимой на SQL Server 2012.
1 ответов
клеевой повязки мы использовали, чтобы отменить наш!--0--> событие после определения целевых и развернутых библиотек DLL и до инициализации базы данных. Это будет отлично работать в нашей текущей ситуации, потому что мы развертываем контекст данных только в одной среде.
наше долгосрочное исправление будет создавать отдельные домены приложений для целевого объекта и каждого развертывания.