Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在实体框架核心3.0中播种?_C#_Entity Framework Core_Asp.net Core 3.0 - Fatal编程技术网

C# 如何在实体框架核心3.0中播种?

C# 如何在实体框架核心3.0中播种?,c#,entity-framework-core,asp.net-core-3.0,C#,Entity Framework Core,Asp.net Core 3.0,我正在尝试使用ASP.NET CORE 3.0和EF CORE为数据库添加一些数据 我已经创建了DbContext,并且根据,甚至(我找不到关于这个主题的任何突破性的更改) 模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder) { modelBuilder.Entity().HasData( 新乐队() { Id=Guid.Parse(“e96bf6d6-3c62-41a9-8ecf-1bd23af931c9”), Name=“SomeName”, CreatedOn

我正在尝试使用ASP.NET CORE 3.0和EF CORE为数据库添加一些数据

我已经创建了DbContext,并且根据,甚至(我找不到关于这个主题的任何突破性的更改)

模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
modelBuilder.Entity().HasData(
新乐队()
{
Id=Guid.Parse(“e96bf6d6-3c62-41a9-8ecf-1bd23af931c9”),
Name=“SomeName”,
CreatedOn=newdatetime(1980,2,13),
Description=“SomeDescription”
});
基于模型创建(modelBuilder);
}
这并没有达到我预期的效果:启动应用程序时没有种子(即使在调试期间从某处调用了该方法)

但是,如果添加迁移,迁移将包含相应的insert语句(这不是我要寻找的种子类型)

问题:在应用程序启动时执行数据库种子的正确方法是什么

通过对数据库进行种子设定,我的意思是,我希望每次启动应用程序时,都能确保某些表中的某些数据


我可以选择创建一个种子类并在数据库之后处理它。使用自定义代码进行迁移,但这似乎是一个解决方法,因为文档指定应使用OnModelCreating来种子数据)



因此,在阅读了答案并重新阅读了文档之后,我的理解是,“种子”指的是可以在数据模型旁边进行的“初始化”(这就是为什么感觉奇怪的原因——将模型创建与数据种子部分混合在一起)。

如果您想在应用程序启动时种子,在应用程序启动方法中,可以使用条件检查来检查所需的数据,如果没有返回,则将这些类添加到上下文中并保存更改

EF Core中的种子是为迁移而设计的,它的初始化数据用于数据库,而不是用于应用程序运行时。如果你想要一组数据不变,那么考虑使用另一种方法吗?例如,通过带有字段检查的属性进行内存缓存,将其保持为xml/json格式

您可以在应用程序启动时使用删除/创建语法,但它通常不受欢迎,因为状态缺乏持久性


不幸的是,对于您想要的内容,它必须是一个解决方案,因为它不在EF的预期功能范围内。

我不认为
OnModelCreating()
是为数据库播种的最佳场所。我认为这完全取决于您希望何时运行播种逻辑。您说过希望在应用程序启动时运行种子设定,而不管数据库是否有迁移更改

我将创建一个扩展方法,以钩住Startup.cs类中的
Configure()
方法:

Startup.cs:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.MigrateAndSeedDb(development: true);
            }
            else
            {
                 app.MigrateAndSeedDb(development: false);
            }           

            app.UseHttpsRedirection();
 ...
MigrateAndSeedDb.cs

 public static void MigrateAndSeedDb(this IApplicationBuilder app, bool development = false)
        {
            using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
            using (var context = serviceScope.ServiceProvider.GetService<GatewayDbContext>())
            {
                //your development/live logic here eg:
                context.Migrate();
                if(development)
                    context.Seed();
            }                
        }

        private static void Migrate(this GatewayDbContext context)
        {
            context.Database.EnsureCreated();
            if (context.Database.GetPendingMigrations().Any())
                context.Database.Migrate();
        }

        private static void Seed(this GatewayDbContext context)
        {
            context.AddOrUpdateSeedData();
            context.SaveChanges();
        }

若你们有复杂的种子数据,那个么使用默认的EF核心特性并不是一个好主意。例如,无法根据配置或系统环境添加种子数据

我正在使用自定义服务和依赖注入来添加种子数据,并在应用程序启动时为上下文应用任何挂起的迁移。我将分享我的定制服务,希望它有助于:

IDbInitializer.cs

公共接口初始值设定项
{
/// 
///将上下文的所有挂起迁移应用于数据库。
///如果数据库不存在,将创建该数据库。
/// 
void初始化();
/// 
///向数据库添加一些默认值
/// 
void SeedData();
}
DbInitializer.cs

公共类DbInitializer:IDbInitializer{
专用读写器ViceScopeFactory\u scopeFactory;
公共数据库初始值设定项(IServiceScopeFactory范围工厂){
这。_scopeFactory=scopeFactory;
}
公共无效初始化(){
使用(var serviceScope=\u scopeFactory.CreateScope()){
使用(var context=serviceScope.ServiceProvider.GetService()){
context.Database.Migrate();
}
}
}
公共数据(){
使用(var serviceScope=\u scopeFactory.CreateScope()){
使用(var context=serviceScope.ServiceProvider.GetService()){
//添加管理员用户
如果(!context.Users.Any()){
var adminUser=新用户{
IsActive=true,
Username=“admin”,
Password=“admin1234”,//应为哈希
SerialNumber=Guid.NewGuid().ToString()
};
context.Users.Add(adminUser);
}
context.SaveChanges();
}
}
}
}
要使用此服务,您可以将其添加到服务集合中:

//StartUp.cs--配置服务方法
services.AddScoped()
因为我想在每次程序启动时使用此服务,所以我使用注入式服务的方式如下:

//StartUp.cs--配置方法
var scopeFactory=app.ApplicationServices.GetRequiredService();
使用(var scope=scopeFactory.CreateScope()){
var dbInitializer=scope.ServiceProvider.GetService();
初始化();
dbInitializer.SeedData();
}

您可以对其使用迁移。只需创建一个新的迁移(不需要事先更改模型类)。生成的迁移类将具有empty Up()和Down()方法。 你可以在那里播种。比如:

protected override void Up(MigrationBuilder migrationBuilder)
{
  migrationBuilder.Sql("your sql statement here...");
}
就这样。

就这样

 public class Program
{
    public static void Main(string[] args)
    {
        var host = CreateHostBuilder(args).Build();

        using (var scope = host.Services.CreateScope())
        {
            var services = scope.ServiceProvider;
            try
            {
                SeedDatabase.Initialize(services);
            }
            catch (Exception ex)
            {
                var logger = services.GetRequiredService<ILogger<Program>>();
                logger.LogError(ex, "An error occured seeding the DB");
            }
        }
        host.Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args)
    {
        var hb = Host.CreateDefaultBuilder(args)
             .ConfigureWebHostDefaults(webBuilder =>
             {
                 webBuilder.UseStartup<Startup>();
             });
        return hb;
    }
   
       
}
公共类
protected override void Up(MigrationBuilder migrationBuilder)
{
  migrationBuilder.Sql("your sql statement here...");
}
 public class Program
{
    public static void Main(string[] args)
    {
        var host = CreateHostBuilder(args).Build();

        using (var scope = host.Services.CreateScope())
        {
            var services = scope.ServiceProvider;
            try
            {
                SeedDatabase.Initialize(services);
            }
            catch (Exception ex)
            {
                var logger = services.GetRequiredService<ILogger<Program>>();
                logger.LogError(ex, "An error occured seeding the DB");
            }
        }
        host.Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args)
    {
        var hb = Host.CreateDefaultBuilder(args)
             .ConfigureWebHostDefaults(webBuilder =>
             {
                 webBuilder.UseStartup<Startup>();
             });
        return hb;
    }
   
       
}
  public static class SeedDatabase
{
    public static void Initialize(IServiceProvider serviceProvider)
    {
        using (var context = new HospitalManagementDbContext(serviceProvider.GetRequiredService<DbContextOptions<HospitalManagementDbContext>>()))
        {
            if (context.InvestigationTags.Any())
            {
                return;
            }

            context.InvestigationTags.AddRange(
                new Models.InvestigationTag
                {
                    Abbreviation = "A1A",
                    Name = "Alpha-1 Antitrypsin"
                },

                new Models.InvestigationTag
                {
                    Abbreviation = "A1c",
                    Name = "Hemoglobin A1c"
                },


                new Models.InvestigationTag
                {
                    Abbreviation = "Alk Phos",
                    Name = "Alkaline Phosphatase"
                }
                );
            context.SaveChanges();
        }
    }
}