Свойство навигации без объявления внешнего ключа

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

Поэтому мой вопрос: можете ли вы иметь навигационное свойство и объявить его как таковое с помощью атрибута?

public class User : IAuditable
{
    // other code

    public virtual User Creator { get; set; }

    public virtual User Modifier { get; set; }
}

1 ответ

Решение

Я считаю, что невозможно определить отношения только с атрибутами данных. Проблема заключается в том, что в соглашениях EF о картографии предполагается, что Creator а также Modifier являются двумя сторонами одного и того же отношения, но не могут определить, что является основным и что является зависимым от этого объединения. Насколько я вижу в списке поддерживаемых атрибутов, нет никакой возможности определить основной и зависимый конец с аннотациями данных.

Кроме того, я предполагаю, что на самом деле вам нужны два отношения, оба с концом, который не представлен в модели. Это означает, что ваша модель является "нетрадиционной" в отношении соглашений об отображении. (Я думаю, что отношения между Creator а также Modifier это на самом деле ерунда - с семантической точки зрения.)

Итак, в Fluent API вы хотите это:

modelBuilder.Entity<User>()
            .HasRequired(u => u.Creator)
            .WithMany();

modelBuilder.Entity<User>()
            .HasRequired(u => u.Modifier)
            .WithMany();

Потому что User может быть создателем или модификатором многих других записей пользователя. Правильно?

Если вы хотите создать эти две взаимосвязи без Fluent API и только с DataAnnotations, я думаю, что вы должны ввести в вашу модель множество концов, например:

public class User
{
    public int UserId { get; set; }

    [InverseProperty("Creator")]
    public virtual ICollection<User> CreatedUsers { get; set; }
    [InverseProperty("Modifier")]
    public virtual ICollection<User> ModifiedUsers { get; set; }

    [Required]
    public virtual User Creator { get; set; }
    [Required]
    public virtual User Modifier { get; set; }
}

Я предполагаю, что здесь Creator а также Modifier требуются, в противном случае мы можем опустить [Required] приписывать.

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

Другие вопросы по тегам