我正在考虑进行迁移,并在迁移中播种数据。我不确定我是否希望种子成为我的迁移的一部分,也许有时候我想要一个干净的石板。
上一次我在大约一年前在Windows上做过asp.net我有以下实现:
using System.Collections.Generic;
using System.Data.Entity.Validation;
using Mentor.Models;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
/**
* Author: matti
*/
namespace Mentor.Migrations
{
using System;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq;
internal sealed class Configuration : DbMigrationsConfiguration<Mentor.Models.ApplicationDbContext>
{
public Configuration()
{
/*if (System.Diagnostics.Debugger.IsAttached == false)
System.Diagnostics.Debugger.Launch();*/
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;
ContextKey = "Mentor.Models.ApplicationDbContext";
}
protected override void Seed(Mentor.Models.ApplicationDbContext context)
{
try
{
var passwordHasher = new PasswordHasher();
User user1 = new User()
{
UserName = "mattinielsen5@hotmail.com",
PasswordHash = passwordHasher.HashPassword("Denherpderp21!"),
FirstName = "Matti andreas",
LastName = "Nielsen",
Age = 24,
ProfileText = "Lorem ipsum dolor sit amet, minimum delicatissimi ad eos, " +
"ne veniam eirmod voluptatibus vel, ne eam facilisi inciderint. " +
"Ex eleifend recteque delicatissimi eos, ut erat posse etiam pri." +
" Ei qui commune vivendum legendos, augue accusata in vim, mei at" +
" bonorum pericula definitionem. Has ornatus aliquando vulputate " +
"at, nonumes docendi in mel. Ne duo recusabo percipitur, et nam " +
"vitae nostrud cotidieque, cibo liber mel te.",
IsMentor = true,
IsMentee = false,
UndefinedInterests = new List<Interest>
{
},
MentorInterests = new List<Interest>
{
},
... blabla alot of entities ...
context.SaveChanges();
}
catch (DbEntityValidationException e)
{
//some error handling
}
}
}
}
所以我想要种子方法,所以我想在startup.cs中调用自己的种子方法,这取决于像开发这样的环境变量。我的问题是,你们是怎么做到的 - 或者你们会怎么做?
编辑:
我正在考虑在创建模型时这样做:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//One-to-one
modelBuilder.Entity<Account>().HasOne(a => a.Player).WithOne(p => p.Account).HasForeignKey<Player>(p => p.AccountForeignKey);
modelBuilder.Entity<Group>().HasOne(g => g.Role).WithOne(r => r.Group).HasForeignKey<Role>(r => r.GroupForeignKey);
modelBuilder.Entity<GameEvent>().HasOne(e => e.Event);
modelBuilder.Entity<GameEvent>().HasOne(e => e.Game);
modelBuilder.Entity<TeamEvent>().HasOne(e => e.Event);
modelBuilder.Entity<TeamEvent>().HasOne(e => e.Team);
modelBuilder.Entity<GroupEvent>().HasOne(e => e.Event);
modelBuilder.Entity<GroupEvent>().HasOne(e => e.Group);
//one-to-many
modelBuilder.Entity<Player>().HasMany(p => p.Integrations).WithOne(i => i.Player);
modelBuilder.Entity<Player>().HasMany(p => p.Followers);
modelBuilder.Entity<Player>().HasMany(p => p.Activities).WithOne(a => a.Player);
modelBuilder.Entity<Game>().HasMany(g => g.GameEvents).WithOne(ge => ge.Game);
modelBuilder.Entity<Game>().HasMany(g => g.Teams).WithOne(t => t.Game);
modelBuilder.Entity<Team>().HasMany(t => t.TeamEvents).WithOne(te => te.Team);
modelBuilder.Entity<Group>().HasMany(g => g.GroupEvents);
//many to many
modelBuilder.Entity<PlayerGames>().HasKey(pg => new {pg.PlayerId, pg.GameId});
modelBuilder.Entity<PlayerTeams>().HasKey(pt => new {pt.PlayerId, pt.TeamId});
modelBuilder.Entity<PlayerGroups>().HasKey(pg => new {pg.PlayerId, pg.GroupId});
//discriminator values
modelBuilder.Entity<Event>()
.HasDiscriminator<string>("Type")
.HasValue<GameEvent>("GameEvent")
.HasValue<GroupEvent>("GroupEvent")
.HasValue<TeamEvent>("TeamEvent");
CALLING SEED DATA DOWN HERE, that should be fine???
}
答案 0 :(得分:3)
建议的方法是在Startup.Configure()
。
它是这样的:
using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
var context = serviceScope.ServiceProvider.GetService<MyContext>();
context.Database.Migrate();
context.EnsureSeedData();
}
您可以在以下链接中查看有关此内容的更多详细信息。
答案 1 :(得分:0)
同意@ Sampath的答案,但是为了快速编辑他的答案而添加了太多内容。一些观察结果:
EF Core
特有的。那是我的情况。 DbMigrationsConfiguration<TContext>.Seed()
方法(来自EF 6
); @ Sampath的链接使the same observation - 所以读者必须通常从EF 5/6
迁移到EF Core
;这也是我的情况。using
返回的新serviceScope的GetService()
,如@Sampath's link中所述,这是在response to this git issue中创建的模式,其中用户已经处理了他们的DbContext 。这种模式也出现在其他答案中,所有这些(except for this one)调用GetService()
或GetRequiredService()
,我认为这不是必要的。我的回答:
您可以直接从依赖注入中获取DbContext到Startup.Configure(...)
@Sampath和两个链接中的任何一个都没有解释context.EnsureSeedData()
中发生的事情(对于一些读者来说可能是显而易见的,但对我来说不是这样)。所以我在下面解释
我相信intro to EF (Core) MVC
提供了解决方案;它创造了:
DbInitializer
Initialize
的静态函数,“确保种子数据存在”。因此,其详细信息(见下文)有助于替代EnsureSeedData()
方法的实施;也许其他用户会觉得有用DbContext
(大概是没有被处理;如果你已经处理它,你应该跟随@ Sampath的回答和/或其他人,which will GetService()
),并可能引入新的using
块Startup.Configure()
中调用(最后?) - 与@ Sampath的静态Initialize
又名“确保种子”功能可以完成以下关键事项:
context.Database.EnsureCreated()
;这实现了“确保”return
;这意味着它是“幂等的”并且可以在每次启动时安全地执行多次,但只能播种一次DbContext.SaveChanges()
如下所示:
public static class DbInitializer
{
public static void Initialize(SchoolContext context)
{
context.Database.EnsureCreated();
// Look for any students.
if (context.Students.Any())
{
return; // DB has been seeded
}
var students = new Student[]
{
new Student{FirstMidName="Carson",LastName="Alexander",EnrollmentDate=DateTime.Parse("2005-09-01")}, ...
};
foreach (Student s in students)
{
context.Students.Add(s);
}
context.SaveChanges();
...
然后使用依赖注入的DbContext
调用该函数,如下所示:
首先,将上下文添加到方法签名中,以便ASP.NET依赖项注入可以将它提供给DbInitializer类.2
public void Configure(..., ..., SchoolContext context)
{
然后在结束时调用你的DbInitializer.Initialize方法 配置方法。
...
DbInitializer.Initialize(context);
}