Могу ли я отключить автоматические отношения в Entity Framework Code First? - PullRequest
8 голосов
/ 30 ноября 2011

Я заметил, что Entity Framework все еще имеет много «автоматических» функций в их последней версии.Как всегда, это действительно обоюдоострый меч.

В частности, я использую событие OnModelBuilder для создания моей модели на лету в коде с использованием fluentAPI (http://msdn.microsoft.com/en-us/library/hh295844(v=vs.103).aspx). У меня большой набор объектов, и они не все соответствуют Microsoft "Стандарты ". Например, мои столбцы идентификаторов называются Person_id вместо PersonId. Таким образом, Entity не всегда автоматически определяет первичный ключ в таблице, или, по крайней мере, кажется, что это не так.

Я не возражаю против того, чтобы быть явным при построении модели, но меня беспокоит то, что Я не всегда уверен, какие свойства и отношения Entity будет автоматически определять, а какие ошибочно игнорировать или ошибочно идентифицировать. Поскольку большинство моих сущностей также имеют частичный класс с вспомогательными методами и свойствами (вещи для обработки перечислений и т. Д.), Я очень боюсь, что однажды Entity автоматически создаст сопоставления между вещами, которые не должны отображаться (ошибка может бытьEntity или какой-то ничего не подозревающий программист).

Есть ли способ, которым я могу отключить auto-Relations-hoity Entity?функция okup, чтобы я мог быть на 100% явным в моем методе OnModelBuilder?Или, как минимум, как я могу узнать, когда мне нужно добавить дополнительные детали отображения (например, необходимость объявить поле необязательным или когда определенное свойство навигации не будет автоматически определено)?

Спасибо!

Ответы [ 5 ]

6 голосов
/ 01 декабря 2011

Автоматическое волшебство выполняется в соответствии с соглашениями внутри кода EF. Вы можете удалить любое из этих соглашений , чтобы отключить какую-то магию, или вы можете удалить их все , и после этого вам нужно будет на 100% явным образом указать свой свободный API.

1 голос
/ 07 марта 2017

Хорошо, поскольку удаление соглашений не работает, есть простой способ не отображать все ненастроенные свойства внутри EF6.x

Основное - использовать отдельные классы отображения и после выполненияРуководство отображает внутри класса, просто вызывает метод, который с помощью отражения заставит игнорировать все свойства, которые не были настроены.

Вот ссылка на мою суть, где реализация.Также добавлен образец в качестве комментария: https://gist.github.com/hidegh/36d92380c720804dee043fde8a863ecb

0 голосов
/ 06 марта 2017

На самом деле этот код удаляет все соглашения, даже очищает исходный набор ...

... но столбцы, не сопоставленные с EntityTypeConfiguration, отображаются ...

private void RemoveAllConventions(DbModelBuilder modelBuilder)
        {
            new List<string>()
            {
            "_configurationConventions",
            "_conceptualModelConventions",
            "_conceptualToStoreMappingConventions",
            "_storeModelConventions"
            }
            .ForEach(field =>
            {
                var values =
                    (IEnumerable<IConvention>)typeof(ConventionsConfiguration)
                        .GetField(field, BindingFlags.Instance | BindingFlags.GetField | BindingFlags.NonPublic)
                        .GetValue(modelBuilder.Conventions);

                modelBuilder.Conventions.Remove(values.ToArray());
            });

            var initialCS = typeof(ConventionsConfiguration)
                        .GetField("_initialConventionSet", BindingFlags.Instance | BindingFlags.GetField | BindingFlags.NonPublic)
                        .GetValue(modelBuilder.Conventions);

            new List<string>()
            {
            "ConfigurationConventions",
            "ConceptualModelConventions",
            "ConceptualToStoreMappingConventions",
            "StoreModelConventions"
            }
           .ForEach(field =>
           {
               var values =
                   (IEnumerable<IConvention>) initialCS
                        .GetType()
                       .GetProperty(field, BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.Public)
                       .GetValue(initialCS);

               modelBuilder.Conventions.Remove(values.ToArray());
           });


        }
0 голосов
/ 01 декабря 2011

Я бы рекомендовал использовать атрибуты аннотации данных для этого.Например, атрибут [key] может использоваться для определения вашего первичного ключа, а атрибут [table] может использоваться для предоставления имени вашей таблицы.Атрибут [required] можно использовать, чтобы сообщить EF, что поле является обязательным.

На мой взгляд, гораздо проще использовать синтаксис атрибута, чем использовать свободный синтаксис для обновления модели, а также самодокументирования, поскольку атрибуты помещаются непосредственно в код объекта.

Для получения дополнительной информации см. Этот пост в блоге, в котором перечислены все доступные атрибуты:

http://blogs.msdn.com/b/efdesign/archive/2010/03/30/data-annotations-in-the-entity-framework-and-code-first.aspx

0 голосов
/ 01 декабря 2011

Просто укажите свои отношения, ключи и столбцы в конфигурации вашей сущности, и это действительно не должно быть проблемой.

Лично я, пока кодирую, допускаю, что пока он не сломается, и затем я исправляю конфигурацию.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    Database.SetInitializer<AccountWriteContext>(null);

    modelBuilder.Configurations.Add(new AccountEntityTypeConfiguration());
    modelBuilder.Configurations.Add(new AccountOwnerEntityTypeConfiguration());
    modelBuilder.Configurations.Add(new CreditCardEntityTypeConfiguration());
    modelBuilder.Configurations.Add(new TenantEntityTypeConfiguration());
    //blah blah blah
}


class AccountOwnerEntityTypeConfiguration
     : EntityTypeConfiguration<AccountOwner>
{
    public AccountOwnerEntityTypeConfiguration()
    {
        this.HasKey(p => p.ID);
        this.Property(p => p.ID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity).IsRequired();

        this.HasRequired(o => o.CreditCard).WithMany().HasForeignKey(c => c.CreditCardID).WillCascadeOnDelete(true);

        this.ToTable("AccountOwner", "AccountWrite");
    }
}
...