实体框架Core 2.0迁移使用种子数据抛出错误更新数据库

时间:2017-11-23 11:56:20

标签: c# entity-framework-core

我正在使用EF Core 2.0代码首次迁移。我试图将迁移罪行运行到新数据库。我正在使用种子数据。如果我使用种子数据我会收到错误,如果我注释掉种子数据方法没有错误。不确定是什么问题。有人可以帮忙吗?

错误:

  

System.Data.SqlClient.SqlException(0x80131904):已经有一个名为' WorkflowBranches'在数据库中。

表已创建,但migrationhistory表中没有记录,即使我有大约5个迁移脚本。还插入了种子数据。

  

我认为数据库已经创建了两次。我正在使用迁移   脚本和种子方法,也有   dbContext.Database.EnsureCreatedAsync()。这可能是原因,但是   我不确定。

Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    //Other code
    services.AddTransient<DbSeeder>();
}

public void Configure(IApplicationBuilder app, 
                      IHostingEnvironment env,
                      DbSeeder dbSeeder)
{
    app.UseMvc();

    dbSeeder.SeedAsync(app.ApplicationServices).Wait();
}

DbSeeder.cs:

using Workflow.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Workflow.DBContext
{
    public class DbSeeder
    {
        readonly ILogger _Logger;

        public DbSeeder(ILoggerFactory loggerFactory)
        {
            _Logger = loggerFactory.CreateLogger("DbSeederLogger");
        }

        public async Task SeedAsync(IServiceProvider serviceProvider)
        {
            //Based on EF team's example at https://github.com/aspnet/MusicStore/blob/dev/samples/MusicStore/Models/SampleData.cs
            using (var serviceScope = serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope())
            {
                var dbContext = serviceScope.ServiceProvider.GetService<WorkflowDBContext>();
                if (await dbContext.Database.EnsureCreatedAsync())
                {
                    if (!await dbContext.Alert.AnyAsync())
                    {
                        await InsertAlertsSampleData(dbContext);
                    }
                }
            }
        }

        public async Task InsertAlertsSampleData(WorkflowDBContext dbContext)
        {
            //Insert Risktypes
            var riskTypes = GetRiskTypes();
            dbContext.RiskType.AddRange(riskTypes);

            try
            {
                int numAffected = await dbContext.SaveChangesAsync();
                _Logger.LogInformation($@"Saved {numAffected} riskTypes");
            }
            catch (Exception exp)
            {
                _Logger.LogError($"Error in {nameof(DbSeeder)}: " + exp.Message);
                throw;
            }

            //Insert categories
            var categories = GetCategories(riskTypes);
            dbContext.Category.AddRange(categories);

            try
            {
                int numAffected = await dbContext.SaveChangesAsync();
                _Logger.LogInformation($"Saved {numAffected} categories");
            }
            catch (Exception exp)
            {
                _Logger.LogError($"Error in {nameof(DbSeeder)}: " + exp.Message);
                throw;
            }

            //var alerts = GetAlerts(categories);
        }

        private List<Alert> GetAlerts(List<Category> categories)
        {
            return new List<Alert>();
        }

        private List<RiskType> GetRiskTypes()
        {
            var riskTypes = new List<RiskType>
            {
                new RiskType { Name = "Risk1"},
                new RiskType { Name = "Risk2"}
            };

            return riskTypes;
        }

        private List<Category> GetCategories(List<RiskType> riskTypes)
        {
            var categoryList = new List<Category>();

            var categories = new string[]
            {
                "Category1Risk1",
                "Category2Risk1",
                "Category3Risk1",
                "Category1Risk2"
            };

            //Low Risk
            foreach (var category in categories.Take(3))
            {
                categoryList.Add(new Category
                {
                    Name = category,
                    RiskType = riskTypes.FirstOrDefault(rt=>rt.Name=='Risk1')
                });
            }

            //High Risk
            foreach (var category in categories.Skip(3))
            {
                categoryList.Add(new Category
                {
                    Name = category,
                    RiskType = riskTypes.FirstOrDefault(rt=>rt.Name=='Risk2')
                });
            }

            return categoryList;
        }
    }
}

由于

1 个答案:

答案 0 :(得分:0)

如果你在Ef Core 2.0中,你需要知道这个:

  

在使用EF Core 2.0的2.0项目中,调用Program.BuildWebHost   获得应用服务。与1.x不同,这有额外的   调用Startup.Configure的副作用。如果您的1.x应用程序被调用   其Configure方法中的数据库初始化代码是意外的   可能会出现问题。例如,如果数据库尚不存在,   播种代码在EF Core Migrations命令执行之前运行。   此问题导致dotnet ef migrations list命令失败   数据库尚不存在。考虑以下1.x种子   Startup.cs的Configure方法中的初始化代码:

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");
});

SeedData.Initialize(app.ApplicationServices);
  

在2.0项目中,将SeedData.Initialize调用移动到Program.cs的Main方法:+

var host = BuildWebHost(args);

using (var scope = host.Services.CreateScope())
{
    var services = scope.ServiceProvider;

    try
    {
        // Requires using RazorPagesMovie.Models;
        SeedData.Initialize(services);
    }
    catch (Exception ex)
    {
        var logger = services.GetRequiredService<ILogger<Program>>();
        logger.LogError(ex, "An error occurred seeding the DB.");
    }
}

host.Run();
  

从2.0开始,在BuildWebHost中执行任何操作都是不好的做法   构建和配置Web主机。任何关于运行的东西   应该在BuildWebHost之外处理应用程序 - 通常在   Program.cs的主要方法。

今天我更改了此代码的代码,mi解决方案正常运行。

我要留下参考链接:

https://docs.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/#move-database-initialization-code