2016-03-04 2 views
3

Я пытаюсь использовать ASP.Net 5 с Entity Framework 7 и SQLite, и я обнаружил странное поведение migrator.EF7 генерирует неправильные миграции с помощью 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); 
    } 

Затем я удалил все файлы из папки «Миграции» и построил решение , Все были готовы к созданию миграций. Я побежал GIT Баш на папке проекта и интер следующих команд:

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

КИ, я увидел файл базы данных и файлы в папке «Миграция», которая выглядит как хорошо. И я предполагаю, что следующая сгенерированная миграция будет пустой без изменений объектной модели. Я пытался сделать это и ввести следующую команду:

$ 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 не поддерживает «ДОБАВИТЬ ВНЕШНИЙ КЛЮЧ». Способ обойти это - перестроить таблицу. Making Other Kinds Of Table Schema Changes на sqlite.org предоставляет инструкции, как структурировать запрос для этого. Вы быстро увидите, насколько это бесполезно на SQLite и почему EF не автоматизирует это для вас.

Если вам не нужны данные в вашей базе данных SQLite, вам, вероятно, лучше просто удалить его и использовать context.Database.EnsureCreated(), чтобы перестроить таблицы с нуля с помощью новой модели.