Исходные данные семян в Entity Framework 7 RC 1 и ASP.NET MVC 6
Похоже, что в Entity Framework 7 еще нет встроенной поддержки семенных данных (https://github.com/aspnet/EntityFramework/issues/629).
В коде шаблона, предоставленном Microsoft, нет метода DbMigrationsConfiguration
class, no Seed
.
Итак, как загружать данные в веб-приложение ASP.NET MVC 6, использующее Entity Framework 7 RC 1?
Ответы
Ответ 1
Я нашел временное обходное решение для себя.
Мы можем создать метод SeedData
, который расширяет IApplicationBuilder
, а затем получает экземпляр нашего класса контекста базы данных с помощью метода GetService
и использует его для посева данных.
Вот как выглядит мой метод расширения:
using Microsoft.AspNet.Builder;
using Microsoft.Extensions.DependencyInjection;
public static class DataSeeder
{
// TODO: Move this code when seed data is implemented in EF 7
/// <summary>
/// This is a workaround for missing seed data functionality in EF 7.0-rc1
/// More info: https://github.com/aspnet/EntityFramework/issues/629
/// </summary>
/// <param name="app">
/// An instance that provides the mechanisms to get instance of the database context.
/// </param>
public static void SeedData(this IApplicationBuilder app)
{
var db = app.ApplicationServices.GetService<ApplicationDbContext>();
// TODO: Add seed logic here
db.SaveChanges();
}
}
Чтобы использовать его, поместите строку app.SeedData();
в метод Configure
класса Startup
приложения (находящегося в веб-проекте в файле с именем Startup.cs
).
// This method gets called by the runtime.
// Use this method to configure the HTTP request pipeline.
public void Configure(
IApplicationBuilder app,
IHostingEnvironment env,
ILoggerFactory loggerFactory)
{
app.SeedData();
// Other configuration code
}
Ответ 2
Для EF Core RTM 1.0 и ASP.NET Core RTM 1.0
Сначала создайте метод семени. Здесь, поскольку мы вышли из области текущего запроса, мы должны создать его manulally:
using System.Collections.Generic;
using System.Linq;
using Core1RtmEmptyTest.Entities;
using Microsoft.Extensions.DependencyInjection;
namespace Core1RtmEmptyTest.Migrations
{
public static class ApplicationDbContextSeedData
{
public static void SeedData(this IServiceScopeFactory scopeFactory)
{
using (var serviceScope = scopeFactory.CreateScope())
{
var context = serviceScope.ServiceProvider.GetService<ApplicationDbContext>();
if (!context.Persons.Any())
{
var persons = new List<Person>
{
new Person
{
FirstName = "Admin",
LastName = "User"
}
};
context.AddRange(persons);
context.SaveChanges();
}
}
}
}
}
Затем укажите правильное время жизни ApplicationDbContext
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(ServiceLifetime.Scoped);
И, наконец, вызовите метод SeedData()
из метода Configure
public void Configure(IServiceScopeFactory scopeFactory)
{
scopeFactory.SeedData();
Ответ 3
Я создал частный Seed()
метод в моем Startup.cs
, но мне также нравится ваш подход, потому что он может использоваться не только во время запуска приложения.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
this.Seed();
}
private void Seed()
{
using (var db = new MyDbContext())
{
db.Database.Migrate();
// Seed code
db.SaveChanges();
}
}
Ответ 4
Из ввод EF/MVC, просто:
- зависимость - введите
DbContext
(SchoolContext
ниже) непосредственно в Startup.Configure()
*
- передайте
DbContext
функции (DbInitializer.Initialize
ниже), которая делает что-то вроде:
- обеспечить, чтобы база данных создала или, которую она перенесла;
context.Database.EnsureCreated();
рассмотрим context.Database.Migrate();
- возвращает, если уже посеял
if (context.Students.Any()) { return; }
- else seed
context.Students.Add({...}); context.SaveChanges();
Как здесь:
public void Configure(..., ..., SchoolContext context)
{
...
DbInitializer.Initialize(context);
}
...
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();
...
* Зависимость - инъекция в Startup.Configure()
- вот почему мой ответ достоин (хотя другой ответ уже принят.)
- Зависимость-впрыскивание
DbContext
в Startup.Configure()
выполняется в EF/MVC Intro
- Никакой другой ответ здесь просто зависит - вводит в Configure; они либо
GetService()
, и/или GetRequiredService()
, либо создают новый DbContext
. Вам может не понадобиться такой код. Опять же, вам может нужен такой код (т.е. Если был установлен DbContext с зависимостями, где находится GetService()
необходимо создать новый Scope. Пожалуйста, уменьшите или отредактируйте/комментарий, если я что-то ошибся.
Ответ 5
Вы можете создать статический метод семени внутри ApplicationDbContext и передать IApplicationBuilder в качестве параметра. Затем вызовите этот метод в Startup.cs
.
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public static void Seed(IApplicationBuilder applicationBuilder)
{
using (var context=applicationBuilder.ApplicationServices.GetRequiredService<ApplicationDbContext>())
{
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
for(int i = 1; i< 1000; i++)
{
context.Movies.Add(new Movie
{
Genre = "Action",
ReleaseDate =DateTime.Today,
Title = "Movie "+i
});
}
context.SaveChanges();
}
}
public DbSet<Movie> Movies { get; set; }
}
В Configure()
внутри Startup.cs
вызовите ApplicationDbContext.Seed(app)
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseIdentity();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
ApplicationDbContext.Seed(app);
}