在程序集 EF6 中找不到上下文类型
No context type was found in the assembly EF6
我正在做一个基于 nopCommerce 的项目。为了更新自定义实体,我想启用 EF 迁移。所以我 运行 以下命令:
Enable-Migrations -StartUpProjectName nop.web -ContextProjectName Nop.Plugin.Payments.Deposit -verbose
并得到错误:
Using StartUp project 'Nop.Web'.
System.Data.Entity.Migrations.Infrastructure.MigrationsException: No context type was found in the assembly 'Nop.Plugin.Payments.Deposit'.
at System.Data.Entity.Utilities.TypeFinder.FindType(Type baseType, String typeName, Func`2 filter, Func`2 noType, Func`3 multipleTypes, Func`3 noTypeWithName, Func`3 multipleTypesWithName)
at System.Data.Entity.Migrations.Design.ToolingFacade.GetContextTypeRunner.Run()
at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
at System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner runner)
at System.Data.Entity.Migrations.Design.ToolingFacade.GetContextType(String contextTypeName)
at System.Data.Entity.Migrations.EnableMigrationsCommand.FindContextToEnable(String contextTypeName)
at System.Data.Entity.Migrations.EnableMigrationsCommand.<>c__DisplayClass2.<.ctor>b__0()
at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command)
No context type was found in the assembly 'Nop.Plugin.Payments.Deposit'.
上下文 class 定义如下:
public class DepositTransactionObjectContext : DbContext, IDbContext
{
public DepositTransactionObjectContext(string nameOrConnectionString) : base(nameOrConnectionString) { }
public DepositTransactionObjectContext() { }
public IList<TEntity> ExecuteStoredProcedureList<TEntity>(string commandText, params object[] parameters) where TEntity : BaseEntity, new()
{
throw new System.NotImplementedException();
}
public IEnumerable<TElement> SqlQuery<TElement>(string sql, params object[] parameters)
{
throw new System.NotImplementedException();
}
public int ExecuteSqlCommand(string sql, bool doNotEnsureTransaction = false, int? timeout = null, params object[] parameters)
{
throw new System.NotImplementedException();
}
public void Detach(object entity)
{
throw new System.NotImplementedException();
}
public bool ProxyCreationEnabled { get; set; }
public bool AutoDetectChangesEnabled { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new DepositTransactionMap());
base.OnModelCreating(modelBuilder);
}
public string CreateDatabaseInstallationScript()
{
return ((IObjectContextAdapter)this).ObjectContext.CreateDatabaseScript();
}
public void Install()
{
//It's required to set initializer to null (for SQL Server Compact).
//otherwise, you'll get something like "The model backing the 'your context name' context has changed since the database was created. Consider using Code First Migrations to update the database"
Database.SetInitializer<DepositTransactionObjectContext>(null);
Database.ExecuteSqlCommand(CreateDatabaseInstallationScript());
SaveChanges();
}
public void Uninstall()
{
this.DropPluginTable("DepositTransaction");
}
public new IDbSet<TEntity> Set<TEntity>() where TEntity : BaseEntity
{
return base.Set<TEntity>();
}
}
我创建了空项目并在那里启用了迁移。然后我复制并调整了 Configuration.cs 使其看起来像这样:
namespace Nop.Plugin.Payments.Deposit.Migrations
{
using Data;
using System.Data.Entity.Migrations;
internal sealed class Configuration : DbMigrationsConfiguration<DepositTransactionObjectContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(DepositTransactionObjectContext context)
{
}
}
}
然而,当我 运行 添加迁移时,出现以下错误:
Using StartUp project 'Nop.Web'.
Using NuGet project 'Nop.Plugin.Payments.Deposit'.
System.Data.Entity.Migrations.Infrastructure.MigrationsException: No migrations configuration type was found in the assembly 'Nop.Plugin.Payments.Deposit'. (In Visual Studio you can use the Enable-Migrations command from Package Manager Console to add a migrations configuration).
at System.Data.Entity.Utilities.TypeFinder.FindType(Type baseType, String typeName, Func`2 filter, Func`2 noType, Func`3 multipleTypes, Func`3 noTypeWithName, Func`3 multipleTypesWithName)
at System.Data.Entity.Migrations.Utilities.MigrationsConfigurationFinder.FindMigrationsConfiguration(Type contextType, String configurationTypeName, Func`2 noType, Func`3 multipleTypes, Func`3 noTypeWithName, Func`3 multipleTypesWithName)
at System.Data.Entity.Migrations.Design.ToolingFacade.BaseRunner.FindConfiguration()
at System.Data.Entity.Migrations.Design.ToolingFacade.ScaffoldRunner.Run()
at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
at System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner runner)
at System.Data.Entity.Migrations.Design.ToolingFacade.Scaffold(String migrationName, String language, String rootNamespace, Boolean ignoreChanges)
at System.Data.Entity.Migrations.AddMigrationCommand.Execute(String name, Boolean force, Boolean ignoreChanges)
at System.Data.Entity.Migrations.AddMigrationCommand.<>c__DisplayClass2.<.ctor>b__0()
at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command)
No migrations configuration type was found in the assembly 'Nop.Plugin.Payments.Deposit'. (In Visual Studio you can use the Enable-Migrations command from Package Manager Console to add a migrations configuration).
我读了很多相同的问题,到处都是原因是在 Enable-Migrations cmdlet 中指定了错误的项目(没有定义上下文)。但正如您所见,这不是我的情况。
还有什么原因?
您还需要添加 -ProjectName 参数来指定您希望迁移到的位置。例如:
Enable-Migrations -ProjectName Nop.Plugin.Payments.Deposit -StartUpProjectName nop.web -ContextProjectName Nop.Plugin.Payments.Deposit -verbose
它应该默认为您在控制台中选择的项目window。 https://coding.abel.nu/2012/03/ef-migrations-command-reference/
太好了,我已经成功解决了这个问题。
为了调查,我下载了 Entity Framework 的源代码并检查了异常堆栈中提到的所有方法。在方法 System.Data.Entity.Utilities.TypeFinder.FindType 中我找到了这样的指令:
var types = _assembly.GetAccessibleTypes()
.Where(t => baseType.IsAssignableFrom(t));
这让我找到了 GetAccessibleTypes() 方法,我发现了这个:
return assembly.DefinedTypes.Select(t => t.AsType());
Having DefinedTypes 是 属性 of System.Reflection.Assembly class 我试图通过在 Powershell 中加载我的程序集并获取此 [=45] 来手动获取此 属性 =]:
$a = [System.Reflection.Assembly]::LoadFrom("P:\nopCommerce\Presentation\Nop.Web\Plugins\Payments.Deposit\Nop.Plugin.Payments.Deposit.dll")
$a.DefinedTypes
结果是空的,因为根本没有类型。
所以我尝试以不同的方式获取类型:
$a.GetTypes()
结果出错:
Exception calling "GetTypes" with "0" argument(s): "Unable to load one
or more of the requested types. Retrieve the LoaderExceptions property
for more information."
当我检查 LoaderException 属性 时,我发现了以下内容:
$Error[0].Exception.InnerException.LoaderExceptions
Could not load file or assembly 'Autofac, Version=3.5.0.0,
Culture=neutral, PublicKeyToken=17863af14b0044da' or one of its
dependencies. The system cannot find the file specified. Could not
load file or assembly 'Nop.Services, Version=3.8.0.0, Culture=neutral,
PublicKeyToken=null' or one of its dependencies. The system cannot
find the file specified. Could not load file or assembly
'System.Web.Mvc, Version=5.2.3.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The
system cannot find the file specified. Could not load file or assembly
'System.Web.Mvc, Version=5.2.3.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The
system cannot find the file specified. Could not load file or assembly
'System.Web.Mvc, Version=5.2.3.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The
system cannot find the file specified. Could not load file or assembly
'System.Web.Mvc, Version=5.2.3.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The
system cannot find the file specified.
看起来 .NET 试图加载所有程序集,我的程序集依赖但当然不能,因为它们不在同一个文件夹中,因为它们是共享的,位于其他地方并由启动项目加载,而不是我的。
因此,我已将所有必需的程序集复制到与我相同的文件夹中,并再次尝试 Enable-Migrations。这次执行没有任何错误!
我问自己为什么不 Enable-Migrations 加载所有这些程序集本身,因为它需要考虑启动项目。但这是个小问题。
我正在做一个基于 nopCommerce 的项目。为了更新自定义实体,我想启用 EF 迁移。所以我 运行 以下命令:
Enable-Migrations -StartUpProjectName nop.web -ContextProjectName Nop.Plugin.Payments.Deposit -verbose
并得到错误:
Using StartUp project 'Nop.Web'.
System.Data.Entity.Migrations.Infrastructure.MigrationsException: No context type was found in the assembly 'Nop.Plugin.Payments.Deposit'.
at System.Data.Entity.Utilities.TypeFinder.FindType(Type baseType, String typeName, Func`2 filter, Func`2 noType, Func`3 multipleTypes, Func`3 noTypeWithName, Func`3 multipleTypesWithName)
at System.Data.Entity.Migrations.Design.ToolingFacade.GetContextTypeRunner.Run()
at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
at System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner runner)
at System.Data.Entity.Migrations.Design.ToolingFacade.GetContextType(String contextTypeName)
at System.Data.Entity.Migrations.EnableMigrationsCommand.FindContextToEnable(String contextTypeName)
at System.Data.Entity.Migrations.EnableMigrationsCommand.<>c__DisplayClass2.<.ctor>b__0()
at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command)
No context type was found in the assembly 'Nop.Plugin.Payments.Deposit'.
上下文 class 定义如下:
public class DepositTransactionObjectContext : DbContext, IDbContext
{
public DepositTransactionObjectContext(string nameOrConnectionString) : base(nameOrConnectionString) { }
public DepositTransactionObjectContext() { }
public IList<TEntity> ExecuteStoredProcedureList<TEntity>(string commandText, params object[] parameters) where TEntity : BaseEntity, new()
{
throw new System.NotImplementedException();
}
public IEnumerable<TElement> SqlQuery<TElement>(string sql, params object[] parameters)
{
throw new System.NotImplementedException();
}
public int ExecuteSqlCommand(string sql, bool doNotEnsureTransaction = false, int? timeout = null, params object[] parameters)
{
throw new System.NotImplementedException();
}
public void Detach(object entity)
{
throw new System.NotImplementedException();
}
public bool ProxyCreationEnabled { get; set; }
public bool AutoDetectChangesEnabled { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new DepositTransactionMap());
base.OnModelCreating(modelBuilder);
}
public string CreateDatabaseInstallationScript()
{
return ((IObjectContextAdapter)this).ObjectContext.CreateDatabaseScript();
}
public void Install()
{
//It's required to set initializer to null (for SQL Server Compact).
//otherwise, you'll get something like "The model backing the 'your context name' context has changed since the database was created. Consider using Code First Migrations to update the database"
Database.SetInitializer<DepositTransactionObjectContext>(null);
Database.ExecuteSqlCommand(CreateDatabaseInstallationScript());
SaveChanges();
}
public void Uninstall()
{
this.DropPluginTable("DepositTransaction");
}
public new IDbSet<TEntity> Set<TEntity>() where TEntity : BaseEntity
{
return base.Set<TEntity>();
}
}
我创建了空项目并在那里启用了迁移。然后我复制并调整了 Configuration.cs 使其看起来像这样:
namespace Nop.Plugin.Payments.Deposit.Migrations
{
using Data;
using System.Data.Entity.Migrations;
internal sealed class Configuration : DbMigrationsConfiguration<DepositTransactionObjectContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(DepositTransactionObjectContext context)
{
}
}
}
然而,当我 运行 添加迁移时,出现以下错误:
Using StartUp project 'Nop.Web'.
Using NuGet project 'Nop.Plugin.Payments.Deposit'.
System.Data.Entity.Migrations.Infrastructure.MigrationsException: No migrations configuration type was found in the assembly 'Nop.Plugin.Payments.Deposit'. (In Visual Studio you can use the Enable-Migrations command from Package Manager Console to add a migrations configuration).
at System.Data.Entity.Utilities.TypeFinder.FindType(Type baseType, String typeName, Func`2 filter, Func`2 noType, Func`3 multipleTypes, Func`3 noTypeWithName, Func`3 multipleTypesWithName)
at System.Data.Entity.Migrations.Utilities.MigrationsConfigurationFinder.FindMigrationsConfiguration(Type contextType, String configurationTypeName, Func`2 noType, Func`3 multipleTypes, Func`3 noTypeWithName, Func`3 multipleTypesWithName)
at System.Data.Entity.Migrations.Design.ToolingFacade.BaseRunner.FindConfiguration()
at System.Data.Entity.Migrations.Design.ToolingFacade.ScaffoldRunner.Run()
at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
at System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner runner)
at System.Data.Entity.Migrations.Design.ToolingFacade.Scaffold(String migrationName, String language, String rootNamespace, Boolean ignoreChanges)
at System.Data.Entity.Migrations.AddMigrationCommand.Execute(String name, Boolean force, Boolean ignoreChanges)
at System.Data.Entity.Migrations.AddMigrationCommand.<>c__DisplayClass2.<.ctor>b__0()
at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command)
No migrations configuration type was found in the assembly 'Nop.Plugin.Payments.Deposit'. (In Visual Studio you can use the Enable-Migrations command from Package Manager Console to add a migrations configuration).
我读了很多相同的问题,到处都是原因是在 Enable-Migrations cmdlet 中指定了错误的项目(没有定义上下文)。但正如您所见,这不是我的情况。
还有什么原因?
您还需要添加 -ProjectName 参数来指定您希望迁移到的位置。例如:
Enable-Migrations -ProjectName Nop.Plugin.Payments.Deposit -StartUpProjectName nop.web -ContextProjectName Nop.Plugin.Payments.Deposit -verbose
它应该默认为您在控制台中选择的项目window。 https://coding.abel.nu/2012/03/ef-migrations-command-reference/
太好了,我已经成功解决了这个问题。
为了调查,我下载了 Entity Framework 的源代码并检查了异常堆栈中提到的所有方法。在方法 System.Data.Entity.Utilities.TypeFinder.FindType 中我找到了这样的指令:
var types = _assembly.GetAccessibleTypes()
.Where(t => baseType.IsAssignableFrom(t));
这让我找到了 GetAccessibleTypes() 方法,我发现了这个:
return assembly.DefinedTypes.Select(t => t.AsType());
Having DefinedTypes 是 属性 of System.Reflection.Assembly class 我试图通过在 Powershell 中加载我的程序集并获取此 [=45] 来手动获取此 属性 =]:
$a = [System.Reflection.Assembly]::LoadFrom("P:\nopCommerce\Presentation\Nop.Web\Plugins\Payments.Deposit\Nop.Plugin.Payments.Deposit.dll")
$a.DefinedTypes
结果是空的,因为根本没有类型。
所以我尝试以不同的方式获取类型:
$a.GetTypes()
结果出错:
Exception calling "GetTypes" with "0" argument(s): "Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information."
当我检查 LoaderException 属性 时,我发现了以下内容:
$Error[0].Exception.InnerException.LoaderExceptions
Could not load file or assembly 'Autofac, Version=3.5.0.0, Culture=neutral, PublicKeyToken=17863af14b0044da' or one of its dependencies. The system cannot find the file specified. Could not load file or assembly 'Nop.Services, Version=3.8.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified. Could not load file or assembly 'System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified. Could not load file or assembly 'System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified. Could not load file or assembly 'System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified. Could not load file or assembly 'System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified.
看起来 .NET 试图加载所有程序集,我的程序集依赖但当然不能,因为它们不在同一个文件夹中,因为它们是共享的,位于其他地方并由启动项目加载,而不是我的。
因此,我已将所有必需的程序集复制到与我相同的文件夹中,并再次尝试 Enable-Migrations。这次执行没有任何错误!
我问自己为什么不 Enable-Migrations 加载所有这些程序集本身,因为它需要考虑启动项目。但这是个小问题。