Сначала модель Entity Framework: программно создайте уникальное ограничение
Я пытаюсь добавить уникальное ограничение в свойство "Имя пользователя" моего объекта / класса "UserAccount". С кодом во-первых, это не будет проблемой, но для модели во-первых, я не могу найти ничего о том, как этого добиться. Дизайнер не поддерживает эту функцию. Я не могу использовать аннотации, потому что классы сущностей генерируются автоматически. Я не могу использовать Fluent API, потому что метод OnModelCreating() не вызывается в модели сначала, и поэтому у меня нет экземпляра DbModelBuilder. Единственное, о чем я могу думать, - это выполнить какой-то ручной SQL-оператор при запуске приложения, который создает ограничение UNIQUE, что в некоторой степени противоречит цели EF. Вот мой текущий класс DbContext:
public partial class UserAccountsModelContainer : DbContext
{
public UserAccountsModelContainer()
: base("name=UserAccountsModelContainer")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<UserAccount> UserAccounts { get; set; }
}
Я даже не буду публиковать класс UserAccount, так как он генерируется автоматически и не должен изменяться (я знаю, что DbContext также генерируется автоматически, но изменение возможно). Любая помощь по этому вопросу приветствуется!
1 ответ
Сначала я рекомендую вам переключиться на Entity Framework Code First. Это дает вам гораздо больше контроля над всем, что возможно с EF.
Я никогда не использовал это раньше, но я знаю Model Conventions
, Они применимы к конфигурации модели. Возможно, это будет подход к настройке соглашения для определенного типа / свойства модели, которое должно быть настроено как уникальное ограничение.
Исходя из следующего, должна быть возможность сначала изменить настройку модели при создании базы данных.
Типовые соглашения основаны на основных метаданных модели. Существуют соглашения как для CSDL, так и для SSDL. Создайте класс, который реализует IConceptualModelConvention из соглашений CSDL, и реализуйте IStoreModelConvention для соглашения SSDL.
Источник: http://www.entityframeworktutorial.net/entityframework6/custom-conventions-codefirst.aspx
Существует два типа условных обозначений: концептуальное (C-Space) и хранилище (S-Space). Это различие указывает, где в конвейере выполняется соглашение. Соглашение C-Space применяется к модели, которую создает приложение, тогда как соглашение S-Space применяется к версии модели.
Источник: https://entityframework.codeplex.com/wikipage?title=Custom%20Conventions
Еще несколько примеров реализации вкл. объяснения находят на MSDN. Я думаю, они очень полезны для вашего случая.
Один пример из MSDN:
public class DiscriminatorRenamingConvention : IStoreModelConvention<EdmProperty>
{
public void Apply(EdmProperty property, DbModel model)
{
if (property.Name == "Discriminator")
{
property.Name = "EntityType";
}
}
}
Это переименует столбец Discriminator в EntityType. Это очень простой пример, но вы можете изменить его, чтобы решить вашу проблему:
public class ModelBasedConvention : IConceptualModelConvention<EdmProperty>
{
public void Apply(EdmProperty property, DbModel model)
{
if (property.Name == "Username"
&& property.DeclaringType.GetType() == typeof(UserAccount))
{
property.AddAnnotation("UniqueKey", property);
}
}
}