Подтвердить что ты не робот

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

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

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

public class User : IAuditable
{
    // other code

    public virtual User Creator { get; set; }

    public virtual User Modifier { get; set; }
}
4b9b3361

Ответ 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 имеет большой смысл и лучше, чем модификация модели, чтобы избежать хорошей конфигурации.