У мене є програма ASP.NET MVC 6, і мені потрібно викликати методи Database.EnsureCreated
and Database.Migrate
.
Але куди мені їх подзвонити?
У мене є програма ASP.NET MVC 6, і мені потрібно викликати методи Database.EnsureCreated
and Database.Migrate
.
Але куди мені їх подзвонити?
Відповіді:
Я вважаю, що це важливе питання, і на нього слід добре відповісти!
Що таке Database.EnsureCreated?
context.Database.EnsureCreated()
- це новий основний метод EF, який гарантує наявність бази даних для контексту. Якщо він існує, ніяких дій не вживається. Якщо вона не існує, то створюється база даних та всі її схеми, а також вона забезпечує її сумісність із моделлю для цього контексту.
Примітка:
Цей метод не використовує міграції для створення бази даних. Крім того, створену базу даних не можна згодом оновити за допомогою міграцій. Якщо ви націлюєтеся на реляційну базу даних і використовуєте міграції, ви можете використовувати DbContext.Database.Migrate()
метод, щоб переконатися, що база даних створена і всі міграції застосовані.
Як ми це зробили з EF 6?
context.Database.EnsureCreated()
еквівалентно наведеним нижче підходам EF 6:
Консоль менеджера пакетів:
Enable-Migrations -EnableAutomaticMigrations. Add-Migration / Update-Database.
З коду:
Database.SetInitializer CreateDatabaseIfNotExists
або
За допомогою DbMigrationsConfiguration та встановіть AutomaticMigrationsEnabled = true;
Що таке Database.Migrate?
Застосовує будь-які очікувані міграції для контексту до бази даних. Створить базу даних, якщо вона ще не існує.
Як ми це зробили з EF 6?
context.Database.Migrate()
еквівалентно наведеним нижче підходам EF 6:
Консоль менеджера пакетів:
Update-Database -TargetMigration
За допомогою власної DbMigrationsConfiguration:
AutomaticMigrationsEnabled = false; або з DbMigrator.
Висновок :
Якщо ви використовуєте міграції, є context.Database.Migrate()
. Якщо ви не хочете міграції і просто хочете швидку базу даних (зазвичай для тестування), тоді використовуйте context.Database.EnsureCreated () / EnsureDeleted ().
Database.Migrate()
міграції Creats (за потреби) потім оновлюють базу на ньому. Подібно до автоматичної міграції в EF 6. Але я помилився. Він застосовує лише існуючі міграції (якщо такі є) у базі даних.
З інформацією, яку надали Джеймс П та Бассам Алуджілі, я в підсумку зробив додавання цих рядків коду до Configure
методу в Startup
класі ( Startup.cs ):
using (var scope =
app.ApplicationServices.CreateScope())
using (var context = scope.ServiceProvider.GetService<MyDbContext>())
context.Database.Migrate();
Просто вперед, ви повинні прочитати це від Роуена Міллера:
...
EnsureCreated
повністю обходить міграції і просто створює схему для вас, ви не можете змішувати це з міграціями.EnsureCreated
призначений для тестування або швидкого створення прототипів, де ви можете щоразу скидати та повторно створювати базу даних. Якщо ви використовуєте міграції та хочете, щоб вони автоматично застосовувались під час запуску програми, тоді ви можете використовувати їхcontext.Database.Migrate()
.
Відповідно до відповіді тут вам потрібно додати Globals.EnsureDatabaseCreated();
його до Startup.cs
:
Функція запуску в Startup.cs :
public Startup(IHostingEnvironment env)
{
// Set up configuration sources.
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables();
if (env.IsDevelopment())
{
// This will push telemetry data through Application Insights pipeline faster, allowing you to view results immediately.
builder.AddApplicationInsightsSettings(developerMode: true);
}
Configuration = builder.Build();
Globals.Configuration = Configuration;
Globals.HostingEnvironment = env;
Globals.EnsureDatabaseCreated();
}
І визначимо Globals.EnsureDatabaseCreated()
таким чином:
public static void EnsureDatabaseCreated()
{
var optionsBuilder = new DbContextOptionsBuilder();
if (HostingEnvironment.IsDevelopment()) optionsBuilder.UseSqlServer(Configuration["Data:dev:DataContext"]);
else if (HostingEnvironment.IsStaging()) optionsBuilder.UseSqlServer(Configuration["Data:staging:DataContext"]);
else if (HostingEnvironment.IsProduction()) optionsBuilder.UseSqlServer(Configuration["Data:live:DataContext"]);
var context = new ApplicationContext(optionsBuilder.Options);
context.Database.EnsureCreated();
optionsBuilder = new DbContextOptionsBuilder();
if (HostingEnvironment.IsDevelopment()) optionsBuilder.UseSqlServer(Configuration["Data:dev:TransientContext"]);
else if (HostingEnvironment.IsStaging()) optionsBuilder.UseSqlServer(Configuration["Data:staging:TransientContext"]);
else if (HostingEnvironment.IsProduction()) optionsBuilder.UseSqlServer(Configuration["Data:live:TransientContext"]);
new TransientContext(optionsBuilder.Options).Database.EnsureCreated();
}
Для використання context.Database.Migrate()
дивіться тут або тут .
Globals
. Це виглядає як нестандартний спосіб спробувати це зробити
Зазвичай DbContext
додається до контейнера для введення залежностей приблизно Startup.ConfigureServices()
так:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add DbContext to the injection container
services.AddDbContext<MyDbContext>(options =>
options.UseSqlServer(
this.Configuration.GetConnectionString("DefaultConnection")));
}
}
Однак, IServiceCollection
він не діє як постачальник послуг, і оскільки DbContext
він не був зареєстрований у контейнері для введення до поточної області дії ( Startup.ConfigureServices
), ми не можемо отримати доступ до контексту за допомогою введення залежності тут.
Хенк Моллем обговорює вручну дозвіл служб при запуску тут , але згадує , що ...
розпізнавання послуг вручну (він же Locator Service), як правило, вважається анти-шаблоном ... [і] вам слід якомога більше уникати цього.
Хенк також зазначає, що Startup
введення залежностей конструктора дуже обмежене і не включає служби, налаштовані на Startup.ConfigureServices()
, тому використання DbContext є найпростішим та найбільш доцільним через контейнер для ін'єкцій, що використовується в іншій частині програми.
Постачальник послуг хостингу середовища виконання може вводити певні послуги в конструктор
Startup
класу, наприкладIConfiguration
,IWebHostEnvironment
(IHostingEnvironment
у версіях до 3.0)ILoggerFactory
таIServiceProvider
. Зверніть увагу, що останній є екземпляром, побудованим хостинговим рівнем, і містить лише основні послуги для запуску програми.
Для того, щоб зателефонувати Database.EnsureCreated()
або Database.Migrate()
ми можемо і хочемо мати автоматичне вирішення DbContext Startup.Configure()
, де наші налаштовані служби тепер доступні через DI:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add DbContext to the injection container
services.AddDbContext<MyDbContext>(options =>
options.UseSqlServer(
this.Configuration.GetConnectionString("DefaultConnection")));
}
public static void Configure(IApplicationBuilder app, IWebHostEnvironment env, MyDbContext context)
{
if (env.IsDevelopment())
{
context.Database.EnsureCreated();
//context.Database.Migrate();
}
}
}
Будь ласка , пам'ятайте , як відповідь Бассама Alugili в посилального від EF Основний документації, Database.EnsureCreated()
і Database.Migrate()
не призначені для використання разом , тому що один гарантує , що ваші існуючі міграції застосовуються до бази даних, яка створюється при необхідності. Інший просто гарантує, що база даних існує, а якщо ні, то створює базу даних, яка відображає вашу DbContext
, включаючи будь-які затравки, зроблені через API Fluent у контексті.