Место для размещения Database.SetInitializer
Я работаю над проектом, который может в итоге иметь несколько версий/вариантов пользовательского интерфейса, но до сих пор у меня есть два подпроекта в моем веб-интерфейсе с веб-интерфейсом ASP.NET MVC. Сервисный проект - это место, где у меня есть мой контекст базы данных и определенные модели.
Моя цель - иметь минимальные или, возможно, ссылки на специальный код EF в моем веб-проекте. Я хочу, чтобы он был независимым, поэтому, когда я переключаю DLL с помощью бэкэнда службы (от SQL Server до SQL или MySQL), я не должен вносить несколько изменений в свой проект MVC.
Вот как это выглядит:
![Project layout]()
Мои вопросы:
- Пока я не нашел примера использования Database.SetInitializer в другом месте, кроме Global.asax. Я хотел бы добавить воссоздание базы данных, если модель изменилась в моем классе factory, например, в классе DatabaseContextProvider или в классе сервиса, который извлекает данные из контекста и предоставляет его в пользовательский интерфейс с DTO. Есть ли недостатки в этом месте?
- Я хотел бы, чтобы контекст connectionString настраивался с помощью файла Properties/Settings.settings - это разумно?
Ответы
Ответ 1
Вам понадобится механизм вызова метода Database.SetInitializer
до самого первого использования DbContext
. Вот почему его обычно вызывают в файле Global.asax
.
Вы можете создать класс с методом инициализации в своем проекте tm.Service
и вызвать его в методе Application_Start
и поместить Database.SetInitializer
в этот метод инициализации.
Его ОК, чтобы указать строку подключения из файла настроек.
Ответ 2
Чтобы избежать связи, я бы предпочел не устанавливать инициализатор вне сборки, содержащий DataContext. Итак, я добавил статический конструктор для DataContext. Таким образом, каждый проект, ссылающийся на эту сборку, будет пользоваться инициализатором без его явной установки, а инициализатор устанавливается только один раз на процесс.
static MyDataContext()
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyDataContext, Configuration>());
}
Строка подключения, конечно, будет взята из файла конфигурации приложения.
Ответ 3
Я помещаю его в конструктор DbContext и работает для меня.
public myDbContext() : base(connectionToDatabase) {
Database.SetInitializer<myDbContext>(null);
}
Решение выше будет работать, но оно не так эффективно, как следующий код:
protected void Application_Start()
{
Database.SetInitializer<myDbContext>(null);
}
В моем случае у меня нет ссылки на мой DAL в пользовательском интерфейсе, и по этой причине я сделал это, я создаю конфигурацию EntityFramework и регистрирую мою настройку, используя отражение.
protected void Application_Start()
{
EntityFrameworkConfig.RegisterSettings();
}
public static class EntityFrameworkConfig
{
public static void RegisterSettings()
{
// Use the file name to load the assembly into the current
// application domain.
Assembly a = Assembly.Load("MyAssembly");
// Get the type to use.
Type myType = a.GetType("MyType");
// Get the method to call.
MethodInfo myMethod = myType.GetMethod("MySettingsMethod");
// Create an instance.
object obj = Activator.CreateInstance(MyType);
// Execute the method.
myMethod.Invoke(obj, null);
}
}
public void Configurations()
{
//Other settings
Database.SetInitializer<myDbContext>(null);
}
Обновление
С Entity Framework 6 теперь вы можете использовать NullDatabaseInitializer
Database.SetInitializer(new NullDatabaseInitializer<MyDbContext>());
Ответ 4
Microsoft предоставила возможность для EF6 и далее конфигурировать один инициализатор для каждого контекста базы данных в файле конфигурации приложения. См. Последний раздел на этой странице Microsoft: https://msdn.microsoft.com/en-us/data/jj556606.aspx
Это, как и подход "Global.asax", имеет то преимущество, что, например, Проекты unit test могут использовать другой инициализатор для одного и того же контекста базы данных.