Entity Framework Core 2.0迁移使用种子数据引发错误更新数据库 [英] Entity Framework Core 2.0 migrations update database with seed data throwing error

查看:71
本文介绍了Entity Framework Core 2.0迁移使用种子数据引发错误更新数据库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用EF Core 2.0代码优先迁移。我试图运行迁移罪到新的数据库。我正在使用种子数据。如果我使用种子数据,则报错,如果注释掉种子数据方法,则报错。不知道是什么问题。有人可以帮忙吗?

I am using EF Core 2.0 code first migration. I am trying to run the migration sin to the new database. I am using seed data. I am getting error if i use seed data and no error if i comment out the seed data method. Not sure what is the problem. Can anyone please help?

错误:


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

System.Data.SqlClient.SqlException (0x80131904): There is already an object named 'WorkflowBranches' in the database.

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

The tables are created, but no records appear in the migrationhistory table, even though I have around 5 migration scripts. Also the seed data is inserted.


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

I think the database is getting created twice. I am using migrations script and also in the seed method, there is dbContext.Database.EnsureCreatedAsync(). This could be the reason but i am not sure.

Startup.cs:

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:

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

谢谢

推荐答案

如果您使用的是Ef Core 2.0,则需要知道以下内容:

If you are in the Ef Core 2.0 you need to kwno this:


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

In 2.0 projects using EF Core 2.0, Program.BuildWebHost is invoked to obtain the application services. Unlike 1.x, this has the additional side effect of invoking Startup.Configure. If your 1.x app invoked database initialization code in its Configure method, unexpected problems can occur. For example, if the database doesn't yet exist, the seeding code runs before the EF Core Migrations command execution. This problem causes a dotnet ef migrations list command to fail if the database doesn't yet exist. Consider the following 1.x seed initialization code in the Configure method of Startup.cs:



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

SeedData.Initialize(app.ApplicationServices);




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

In 2.0 projects, move the SeedData.Initialize call to the Main method of Program.cs:+



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上除$以外的任何操作都是不好的做法b $ b构建和配置Web主机。关于运行
应用程序的所有操作都应在BuildWebHost之外进行处理-通常在
中使用Program.cs的Main方法。

As of 2.0, it's bad practice to do anything in BuildWebHost except build and configure the web host. Anything that is about running the application should be handled outside of BuildWebHost — typically in the Main method of Program.cs.

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

Today i changed my code for this code, and mi solution worked properly.

我给您提供了参考链接:

I am leaving you the reference link:

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

这篇关于Entity Framework Core 2.0迁移使用种子数据引发错误更新数据库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆