簡體   English   中英

EF7使用SQLite生成錯誤的遷移

[英]EF7 generates wrong migrations with SQLite

我嘗試將ASP.Net 5與Entity Framework 7和SQLite一起使用,我發現了一個奇怪的遷移器行為。

我刪除了Visual Studio 2015並使用模板“ASP.NET 5 Template Web Application”創建了一個新項目。

之后我刪除了依賴

"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);
    }

然后我從文件夾“Migrations”中刪除了所有文件並構建了解決方案。 所有人都已准備好創建遷移。 我在項目文件夾上運行git bash並在下一個命令之間運行:

blush@BLUSH /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.

好的,我在“遷移”文件夾中看到了一個數據庫文件和文件。 而且我猜想下一次生成的遷移將是空的,而不會更改對象模型。 我試着這樣做並輸入下一個命令:

$ 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.

這是一個問題:我將如何解決這個問題?

這是SQLite的限制。 請參閱EF中的SQLite限制

這是因為SQLite本身不支持“ADD FOREIGN KEY”。 解決此問題的方法是進行表重建。 在sqlite.org上進行其他類型的表模式更改提供了有關如何構造查詢以執行此操作的說明。 您很快就會發現SQLite有多亂,以及為什么EF不能為您自動化。

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

使用Visual Studio Community 2017 for Mac時,這個問題發生在我身上

我發現最簡單的方法是刪除數據庫並重新創建遷移。 當然,我能夠負擔得起,因為該項目處於開發的早期階段:

  1. 刪除數據庫文件(app.db)
  2. 發出命令dotnet ef migrations remove直到只有第一次遷移( 00000000000000_CreateIdentitySchema
  3. 添加新的遷移dotnet ef migrations add CreatedEntities (例如)
  4. 更新數據庫dotnet ef database update

如果SQLite僅用於內存單元測試,請嘗試以下操作:

if (context.Database.ProviderName == "Microsoft.EntityFrameworkCore.Sqlite")
{
    context.Database.EnsureCreated();
}
else
{
    context.Database.Migrate();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM