【发布时间】:2012-07-25 05:55:49
【问题描述】:
我不确定如何使用代码优先迁移功能。据我了解,如果它不存在,它应该创建我的数据库,并根据迁移文件将其更新为最新模式。但我正在为此苦苦挣扎,因为我总是遇到很多错误,而且我不确定如何正确使用它..
internal class Program
{
private static void Main()
{
EntityFrameworkProfiler.Initialize();
Database.DefaultConnectionFactory = new SqlCeConnectionFactory("System.Data.SqlServerCe.4.0");
Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyContext, Migrations.Configuration>());
using (var context = new MyContext())
{
var exists = context.Database.Exists();
if (!exists)
{
context.Database.Create();
}
var element = context.Dummies.FirstOrDefault();
}
}
}
public class MyContext : DbContext
{
public MyContext()
: base(string.Format(@"DataSource=""{0}""", @"C:\Users\user\Desktop\MyContext.sdf"))
{
}
public DbSet<Dummy> Dummies { get; set; }
}
internal sealed class Configuration : DbMigrationsConfiguration<MyContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(CodeFirstTest.MyContext context)
{
}
}
使用 Entity Framework Profiler 检查执行了哪些语句。当我在不存在数据库的情况下运行程序时,我得到以下输出:
-- 声明 #1 选择 [GroupBy1].[A1] 作为 [C1] 从(选择计数(1)作为 [A1] FROM [__MigrationHistory] AS [Extent1]) AS [GroupBy1]
-- 声明 #2 警告: System.Data.SqlServerCe.SqlCeException (0x80004005):指定的表不存在。 [ __MigrationHistory ] 在 System.Data.SqlServerCe.SqlCeCommand.ProcessResults(Int32 小时) 在 System.Data.SqlServerCe.SqlCeCommand.CompileQueryPlan() 在 System.Data.SqlServerCe.SqlCeCommand.ExecuteCommand(CommandBehavior 行为,String 方法,ResultSetOptions 选项) 在 System.Data.SqlServerCe.SqlCeCommand.ExecuteReader(CommandBehavior 行为) 在 System.Data.SqlServerCe.SqlCeMultiCommand.ExecuteReader(CommandBehavior 行为) 在 System.Data.SqlServerCe.SqlCeMultiCommand.ExecuteDbDataReader(CommandBehavior 行为) 在 HibernatingRhinos.Profiler.Appender.ProfiledDataAccess.ProfiledCommand.ExecuteDbDataReader(CommandBehavior 行为)
-- 声明 #3 选择 [GroupBy1].[A1] 作为 [C1] 从(选择计数(1)作为 [A1] FROM [__MigrationHistory] AS [Extent1]) AS [GroupBy1]
-- 声明 #4 警告: System.Data.SqlServerCe.SqlCeException (0x80004005):指定的表不存在。 [ __MigrationHistory ] 在 System.Data.SqlServerCe.SqlCeCommand.ProcessResults(Int32 小时) 在 System.Data.SqlServerCe.SqlCeCommand.CompileQueryPlan() 在 System.Data.SqlServerCe.SqlCeCommand.ExecuteCommand(CommandBehavior 行为,String 方法,ResultSetOptions 选项) 在 System.Data.SqlServerCe.SqlCeCommand.ExecuteReader(CommandBehavior 行为) 在 System.Data.SqlServerCe.SqlCeMultiCommand.ExecuteReader(CommandBehavior 行为) 在 System.Data.SqlServerCe.SqlCeMultiCommand.ExecuteDbDataReader(CommandBehavior 行为) 在 HibernatingRhinos.Profiler.Appender.ProfiledDataAccess.ProfiledCommand.ExecuteDbDataReader(CommandBehavior 行为)
-- 声明#5 选择 [GroupBy1].[A1] 作为 [C1] 从(选择计数(1)作为 [A1] FROM [__MigrationHistory] AS [Extent1]) AS [GroupBy1]
-- 声明 #6 警告: System.Data.SqlServerCe.SqlCeException (0x80004005):指定的表不存在。 [ __MigrationHistory ] 在 System.Data.SqlServerCe.SqlCeCommand.ProcessResults(Int32 小时) 在 System.Data.SqlServerCe.SqlCeCommand.CompileQueryPlan() 在 System.Data.SqlServerCe.SqlCeCommand.ExecuteCommand(CommandBehavior 行为,String 方法,ResultSetOptions 选项) 在 System.Data.SqlServerCe.SqlCeCommand.ExecuteReader(CommandBehavior 行为) 在 System.Data.SqlServerCe.SqlCeMultiCommand.ExecuteReader(CommandBehavior 行为) 在 System.Data.SqlServerCe.SqlCeMultiCommand.ExecuteDbDataReader(CommandBehavior 行为) 在 HibernatingRhinos.Profiler.Appender.ProfiledDataAccess.ProfiledCommand.ExecuteDbDataReader(CommandBehavior 行为)
-- 声明 #7 选择 [GroupBy1].[A1] 作为 [C1] 从(选择计数(1)作为 [A1] FROM [__MigrationHistory] AS [Extent1]) AS [GroupBy1]
-- 声明 #8 警告: System.Data.SqlServerCe.SqlCeException (0x80004005):指定的表不存在。 [ __MigrationHistory ] 在 System.Data.SqlServerCe.SqlCeCommand.ProcessResults(Int32 小时) 在 System.Data.SqlServerCe.SqlCeCommand.CompileQueryPlan() 在 System.Data.SqlServerCe.SqlCeCommand.ExecuteCommand(CommandBehavior 行为,String 方法,ResultSetOptions 选项) 在 System.Data.SqlServerCe.SqlCeCommand.ExecuteReader(CommandBehavior 行为) 在 System.Data.SqlServerCe.SqlCeMultiCommand.ExecuteReader(CommandBehavior 行为) 在 System.Data.SqlServerCe.SqlCeMultiCommand.ExecuteDbDataReader(CommandBehavior 行为) 在 HibernatingRhinos.Profiler.Appender.ProfiledDataAccess.ProfiledCommand.ExecuteDbDataReader(CommandBehavior 行为)
-- 声明 #9 以隔离级别开始事务:可序列化
-- 声明 #10 创建表 [假人] ( [名称] nvarchar 非空, 约束 [PK_Dummies] 主键([名称]) )
-- 声明 #11 创建表 [迁移历史] ( [MigrationId] nvarchar 非空, [CreatedOn] [日期时间] 非空, [型号] [图片] 不为空, [ProductVersion] nvarchar NOT NULL, 约束 [PK_MigrationHistory] 主键 ([MigrationId]) )
-- 声明 #12 插入 [__MigrationHistory] ([迁移 ID], [创建于], [模型], [产品版本]) 值('201207261524579_InitialCreate', '2012-07-26T15:24:58.523', 0x1F8B080 , '4.3.1')
-- 声明 #13 提交事务
-- 声明 #14 选择顶部 (1) [c].[名称] 作为 [名称] FROM [Dummies] AS [c]
如您所见,它在实际创建数据库之前尝试访问数据库 四次 次。这似乎不对。当我使用现有数据库启动应用程序时,它将在执行任何实际查询之前查询数据库 7 次。请注意,context.Database.Create() 会发生这种情况,.Exists() 不会发生这种情况。
我的配置的种子方法也从未被调用,但构造函数是。
这一切似乎都非常错误和令人困惑。我希望有人能告诉我为什么错误在一开始经常发生,以及为什么我的种子方法根本没有被调用。
我正在使用 SqlServer compact 和 Entity Framework 的最新稳定版本。
package id="EntityFramework" version="4.3.1" targetFramework="net40"
包 id="Microsoft.SqlServer.Compact" 版本="4.0.8854.2" targetFramework="net40"
【问题讨论】:
-
尝试在第一次调用
DbContext之前将Database静态调用移出构造函数。 -
@SergRogovtsev 不幸的是,这并没有改变。
-
请您相应地更新您的代码吗?
-
@Martin1921 好吧,你当然是对的。我自己试过这个 sn-p,我可以看到如果数据库不存在,它会检查 4 次是否存在 __MigrationHistory 表(我尝试设置 AutomaticMigrationsEnabled = false 以防它为您的手动迁移和 EF 的自动复制迁移,但仍然完全相同)。当我第二次运行我的代码(在初始数据库创建之后)但不是第一次运行时,我的种子方法运行。
标签: c# ef-code-first sql-server-ce-4 entity-framework-migrations