Свойство навигации без объявления внешнего ключа - PullRequest
30 голосов
/ 17 апреля 2011

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

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

public class User : IAuditable
{
    // other code

    public virtual User Creator { get; set; }

    public virtual User Modifier { get; set; }
}

1 Ответ

35 голосов
/ 17 апреля 2011

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

...