Entity framework Can';t在实体框架4.3中启用迁移
我有一个带有EF代码的类库。我刚刚升级到EF 4.3,现在我想启用迁移 我在PM控制台中键入Entity framework Can';t在实体框架4.3中启用迁移,entity-framework,entity-framework-migrations,entity-framework-4.3,Entity Framework,Entity Framework Migrations,Entity Framework 4.3,我有一个带有EF代码的类库。我刚刚升级到EF 4.3,现在我想启用迁移 我在PM控制台中键入启用迁移-ProjectName MyProjectName,但收到以下错误 PM> Enable-Migrations -ProjectName MyProjectName System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary. at System.Co
启用迁移-ProjectName MyProjectName
,但收到以下错误
PM> Enable-Migrations -ProjectName MyProjectName
System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
at System.Data.Entity.Migrations.DbMigrationsConfiguration.GetSqlGenerator(String providerInvariantName)
at System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration, DbContext usersContext)
at System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration)
at System.Data.Entity.Migrations.Design.MigrationScaffolder..ctor(DbMigrationsConfiguration migrationsConfiguration)
at System.Data.Entity.Migrations.Design.ToolingFacade.ScaffoldRunner.RunCore()
at System.Data.Entity.Migrations.Design.ToolingFacade.BaseRunner.Run()
The given key was not present in the dictionary.
PM>
我想不出哪本字典可能错了
我的连接字符串如下所示:
<connectionStrings>
<add name="MySystem" connectionString="Data Source=MyServer\Instance;Initial Catalog=myDbName;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionStrings>
你知道有什么不对吗
请注意:我在控制台应用程序中使用类库和app.config的精确副本,在那里我可以很好地访问我的数据库。EF Code首先有一个用于Sql代码生成的可扩展提供程序模型。
DbMigrationsConfiguration.GetSqlGenerator
的文档说明了它的功能:
获取设置为与给定数据库一起使用的SQL生成器
提供者
MvcMiniProfiler将自己包装在DB提供程序周围,以添加分析支持。要执行EF,看起来您使用的是MvcMiniProfiler数据库,而不是MSSQL数据库。不幸的是,EF代码首先不知道如何处理MvcMiniProfiler数据库
一个可能的修复方法是添加一个具有MvcMiniProfiler名称的SqlGenerator,该名称包装Sql Server生成器
编辑
看起来可以为mvc迷你探查器名称重新注册现有的sql server生成器(如果您知道它的名称的话)
在,有一段代码片段显示了如何注册提供程序:
public Configuration()
{
AutomaticMigrationsEnabled = false;
SetSqlGenerator("System.Data.SqlClient",
new CustomMigrationsProviders.CustomSqlServerMigrationSqlGenerator());
}
事实证明安德斯·亚伯的原因是正确的,但我们找到了一个简单得多的解决办法
据介绍,Nuget中有一个名为
MiniProfiler.EF
的特殊包,它不需要SqlConnection
的任何包装。我们放弃了旧的mvc迷你探查器,安装了MiniProfiler.EF
。然后,启用迁移
按预期工作。这可能是一个相关但不同的问题,但由于是Anders在这里的帖子引导我找到了解决方案,我想我也在这里发布了这个解决方案
问题:
如果在执行实体框架数据库初始化策略之前初始化了MiniProfiler,则初始化会失败,并出现一个关于缺少迁移表的错误
如果首先执行Entity Framework数据库初始化策略,则对实体的访问将失败,并出现类型转换异常,因为MiniProfiler DbConnection试图强制进入SqlConnection变量(在内部泛型中)
原因:
当MiniProfiler初始化时,它使用反射从System.Data.Common.DbProviderFactorys中的私有静态字段检索数据库提供程序的集合。然后,它使用MiniProfiler垫片提供程序重写此列表,以替换本机提供程序。这允许MiniProfiler以静默方式拦截对数据库的任何调用
当实体框架初始化时,它开始编译数据模型,并在一些私有静态字段中创建存储在System.data.Entity.Internal.LazyInternalContext中的缓存初始化数据库。一旦创建了这些,针对DbContext的查询将使用缓存的模型和数据库,这些模型和数据库在内部类型化,以使用初始化时存在的提供程序
当实体框架数据库初始化策略运行时,它需要访问原始Sql提供程序,而不是MiniProfiler垫片,以便正确生成Sql以创建表。但是,一旦对本机提供程序进行了这些调用,本机提供程序就会被缓存到LazyInternalContext中,如果没有运行时故障,我们就无法再注入MiniProfiler
我的解决方案:
访问System.Data.Entity.Internal.LazyInternalContext中的私有集合,并清除缓存的编译模型和初始化的数据库
如果我在EF数据库初始化策略的操作和MiniProfiler的初始化之间执行此清除,则可以插入MiniProfiler垫片,而不会导致以后的运行时故障
代码:
这段代码帮了我的忙:
Type type = typeof(DbContext).Assembly.GetType("System.Data.Entity.Internal.LazyInternalContext");
object concurrentDictionary = (type.GetField("InitializedDatabases", BindingFlags.NonPublic | BindingFlags.Static)).GetValue(null);
var initializedDatabaseCache = (IDictionary)concurrentDictionary;
if (initializedDatabaseCache != null) initializedDatabaseCache.Clear();
object concurrentDictionary2 = (type.GetField("CachedModels", BindingFlags.NonPublic | BindingFlags.Static)).GetValue(null);
var modelsCache = (IDictionary)concurrentDictionary2;
if (modelsCache != null) modelsCache.Clear();
警告:
LazyInternalContext中的内部字段的名称在EF的不同版本之间可能会发生变化,因此您可能需要修改此代码以使用项目中包含的EF的确切版本。看起来MvcMiniProfiler可能是罪魁祸首。删除它可以启用迁移。