2016-03-04 64 views
3

我嘗試使用ASP.Net 5與Entity Framework 7和SQLite,並且發現了一個奇怪的遷移行爲。EF7使用SQLite生成錯誤的遷移

我提取了Visual Studio 2015並創建了一個模板爲「ASP.NET 5 Template Web Application」的新項目。

在那之後我刪除dependecy

"EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final" 

而且增加了兩個依賴,以及比所謂的恢復包。

"EntityFramework.Sqlite": "7.0.0-rc1-final", 
"Microsoft.Data.Sqlite": "1.0.0-rc1-final" 

就像那個

"dependencies": { 
"EntityFramework.Commands": "7.0.0-rc1-final", 
"EntityFramework.Sqlite": "7.0.0-rc1-final", 
"Microsoft.Data.Sqlite": "1.0.0-rc1-final", 
"Microsoft.AspNet.Authentication.Cookies": "1.0.0-rc1-final", 
"Microsoft.AspNet.Diagnostics.Entity": "7.0.0-rc1-final", 
"Microsoft.AspNet.Identity.EntityFramework": "3.0.0-rc1-final", 
"Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final", 
"Microsoft.AspNet.Mvc": "6.0.0-rc1-final", 
"Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-rc1-final", 
"Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final", 
"Microsoft.AspNet.StaticFiles": "1.0.0-rc1-final", 
"Microsoft.AspNet.Tooling.Razor": "1.0.0-rc1-final", 
"Microsoft.Extensions.CodeGenerators.Mvc": "1.0.0-rc1-final", 
"Microsoft.Extensions.Configuration.FileProviderExtensions": "1.0.0-rc1-final", 
"Microsoft.Extensions.Configuration.Json": "1.0.0-rc1-final", 
"Microsoft.Extensions.Configuration.UserSecrets": "1.0.0-rc1-final", 
"Microsoft.Extensions.Logging": "1.0.0-rc1-final", 
"Microsoft.Extensions.Logging.Console": "1.0.0-rc1-final", 
"Microsoft.Extensions.Logging.Debug": "1.0.0-rc1-final", 
"Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0-rc1-final" 
} 

接下來我去Startup.cs和更改的功能ConfigurationServices像

public void ConfigureServices(IServiceCollection services) 
    { 
     // Add framework services. 
     var dbFilePath =  Path.Combine(PlatformServices.Default.Application.ApplicationBasePath, "test.db"); 
     services.AddEntityFramework() 
     .AddSqlite() 
     .AddDbContext<ApplicationDbContext>(options => 
      options.UseSqlite("Filename=" + dbFilePath)); 
     System.Console.WriteLine("Use DB file:" + dbFilePath); 

     services.AddIdentity<ApplicationUser, IdentityRole>() 
      .AddEntityFrameworkStores<ApplicationDbContext>() 
      .AddDefaultTokenProviders(); 

     services.AddMvc(); 

     // Add application services. 
     services.AddTransient<IEmailSender, AuthMessageSender>(); 
     services.AddTransient<ISmsSender, AuthMessageSender>(); 
     services.AddInstance<IConfigurationRoot>(Configuration); 
    } 

然後,我從文件夾「遷移」刪除所有文件和內置的解決方案。 所有已準備好創建遷移。 我跑項目文件夾和跨下一個命令的git bash下

[email protected] /d/dev/testMVC 
$ dnx ef migrations add firstMigration 
Use DB file:D:\dev\testMVC\test.db 
Done. To undo this action, use 'ef migrations remove' 

$ dnx ef database update 
Use DB file:D:\dev\testMVC\test.db 
Applying migration '20160304130532_firstMigration'. 
Done. 

OK,我看到了一個數據庫文件和文件夾中的「遷移」,它看起來像好。 我猜想下一次生成的遷移將是空的,而不會更改對象模型。 我試圖做到這一點,並進入下一個命令:

$ dnx ef migrations add testMigration 
Use DB file:D:\dev\testMVC\test.db 
Done. To undo this action, use 'ef migrations remove' 

我去看了產生遷移類,我看到這樣的代碼:

protected override void Up(MigrationBuilder migrationBuilder) 
     { 
      migrationBuilder.DropForeignKey(name: "FK_IdentityRoleClaim<string>_IdentityRole_RoleId", table: "AspNetRoleClaims"); 
      migrationBuilder.DropForeignKey(name: "FK_IdentityUserClaim<string>_ApplicationUser_UserId", table: "AspNetUserClaims"); 
      migrationBuilder.DropForeignKey(name: "FK_IdentityUserLogin<string>_ApplicationUser_UserId", table: "AspNetUserLogins"); 
      migrationBuilder.DropForeignKey(name: "FK_IdentityUserRole<string>_IdentityRole_RoleId", table: "AspNetUserRoles"); 
      migrationBuilder.DropForeignKey(name: "FK_IdentityUserRole<string>_ApplicationUser_UserId", table: "AspNetUserRoles"); 
      migrationBuilder.AddForeignKey(
       name: "FK_IdentityRoleClaim<string>_IdentityRole_RoleId", 
       table: "AspNetRoleClaims", 
       column: "RoleId", 
       principalTable: "AspNetRoles", 
       principalColumn: "Id", 
       onDelete: ReferentialAction.Cascade); 
      migrationBuilder.AddForeignKey(
       name: "FK_IdentityUserClaim<string>_ApplicationUser_UserId", 
       table: "AspNetUserClaims", 
       column: "UserId", 
       principalTable: "AspNetUsers", 
       principalColumn: "Id", 
       onDelete: ReferentialAction.Cascade); 
      migrationBuilder.AddForeignKey(
       name: "FK_IdentityUserLogin<string>_ApplicationUser_UserId", 
       table: "AspNetUserLogins", 
       column: "UserId", 
       principalTable: "AspNetUsers", 
       principalColumn: "Id", 
       onDelete: ReferentialAction.Cascade); 
      migrationBuilder.AddForeignKey(
       name: "FK_IdentityUserRole<string>_IdentityRole_RoleId", 
       table: "AspNetUserRoles", 
       column: "RoleId", 
       principalTable: "AspNetRoles", 
       principalColumn: "Id", 
       onDelete: ReferentialAction.Cascade); 
      migrationBuilder.AddForeignKey(
       name: "FK_IdentityUserRole<string>_ApplicationUser_UserId", 
       table: "AspNetUserRoles", 
       column: "UserId", 
       principalTable: "AspNetUsers", 
       principalColumn: "Id", 
       onDelete: ReferentialAction.Cascade); 
     } 

     protected override void Down(MigrationBuilder migrationBuilder) 
     { 
     ... 
     } 

如果我嘗試應用這種遷移,趕上下一個錯誤消息:

$ dnx ef database update 
Use DB file:D:\dev\testMVC\test.db 
Applying migration '20160304133144_testMigration'. 
System.NotSupportedException: SQLite cannot support this migration operation. 
    в Microsoft.Data.Entity.Migrations.SqliteMigrationsSqlGenerator.Generate(Drop 
ForeignKeyOperation operation, IModel model, RelationalCommandListBuilder builde 
r) 
    в Microsoft.Data.Entity.Migrations.MigrationsSqlGenerator.<>c.<.cctor>b__50_1 
0(MigrationsSqlGenerator g, MigrationOperation o, IModel m, RelationalCommandLis 
tBuilder b) 
    в Microsoft.Data.Entity.Migrations.MigrationsSqlGenerator.Generate(MigrationO 
peration operation, IModel model, RelationalCommandListBuilder builder) 
    в Microsoft.Data.Entity.Migrations.MigrationsSqlGenerator.Generate(IReadOnlyL 
ist`1 operations, IModel model) 
    в Microsoft.Data.Entity.Migrations.SqliteMigrationsSqlGenerator.Generate(IRea 
dOnlyList`1 operations, IModel model) 
    в Microsoft.Data.Entity.Migrations.Internal.Migrator.GenerateUpSql(Migration 
migration) 
    в Microsoft.Data.Entity.Migrations.Internal.Migrator.<>c__DisplayClass12_4.<G 
etMigrationCommands>b__10() 
    в Microsoft.Data.Entity.Migrations.Internal.Migrator.Migrate(String targetMig 
ration) 
    в Microsoft.Data.Entity.Design.MigrationsOperations.UpdateDatabase(String tar 
getMigration, String contextType) 
    в Microsoft.Data.Entity.Commands.Program.Executor.<>c__DisplayClass7_0.<Updat 
eDatabase>b__0() 
    в Microsoft.Data.Entity.Commands.Program.Executor.Execute(Action action) 
SQLite cannot support this migration operation. 

而這個問題:我該怎麼辦才能解決這個問題?

回答

5

這是SQLite的限制。請參閱SQLite Limitations in EF

發生這種情況是因爲SQLite本身不支持「添加外鍵」。解決此問題的方法是執行表重建。 sqlite.org上的Making Other Kinds Of Table Schema Changes提供瞭如何構建查詢來執行此操作的說明。你會很快看到這是多麼凌亂在SQLite和爲什麼EF不會爲你自動化。

如果你不需要你的SQLite數據庫中的數據,你可能最好只是刪除它,並使用context.Database.EnsureCreated()從頭開始使用你的新模型重建表。