c# - EF7 使用 SQLite 生成错误的迁移

标签 c# sqlite migration entity-framework-core dnx

我尝试将 ASP.Net 5 与 Entity Framework 7 和 SQLite 一起使用,我发现了一个奇怪的迁移器行为。

我使用了 Visual Studio 2015 并使用模板“ASP.NET 5 模板 Web 应用程序”创建了一个新项目。

之后我删除了依赖

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

好的,我在“Migrations”文件夹中看到了一个数据库文件和文件,看起来不错。 而且我猜想下一个生成的迁移将是空的,而不会更改对象模型。 我尝试这样做并输入下一个命令:

$ 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 的限制。参见 SQLite Limitations in EF .

发生这种情况是因为 SQLite 本身不支持“ADD FOREIGN KEY”。解决此问题的方法是重建表。 Making Other Kinds Of Table Schema Changes在 sqlite.org 上提供了有关如何构造查询以执行此操作的说明。您将很快看到这在 SQLite 上有多困惑,以及为什么 EF 不为您自动执行此操作。

如果您不需要 SQLite 数据库中的数据,您最好删除它并使用 context.Database.EnsureCreated() 使用您的新模型从头开始重建表.

关于c# - EF7 使用 SQLite 生成错误的迁移,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35797628/

相关文章:

c# - C# 中的 Telegram Bot 自定义键盘

c# - 在 MonoTouch 中获取用户国家代码 (ISO 3166-1)

c# - c# 编译器是否会执行多个隐式转换以从一种类型转换为另一种类型?

android - DbAdapter 类与 ContentProvider 在 android 中有什么区别?

javascript - TypeScript 可以与现有的 JavaScript 代码一起使用吗?

c# - 需要 SearchBar 给出相同的结果,无论其字母是否大写

android - SQLite 外键错误 Android

javascript - 将 Express 应用程序迁移到 NestJS

mysql - 使用 Phinx Migrate 添加 'varbinary' MySQL 字段类型

android - 如何从 sqlite 游标中获取列值?