EF Code First - WithMany()

Недавно я пришел к классу ManyNavigationPropertyConfiguration<TEntity, TTarget> , и внутри этого класса я нашел метод с именем WithMany() с двумя перегрузками.

Первая перегрузка: WithMany()

Настраивает отношение многие: многие без навигации собственности на другой стороне отношения.

Вторая перегрузка: WithMany(Expression<Func<TTarget, ICollection<TEntity>>>)

Настраивает отношение многие: многие с навигационным свойством с другой стороны отношений.

Теперь мой вопрос: почему бы вам настроить отношение как много: многие без свойства навигации (первая перегрузка)? Я не вижу никаких сценариев, где это было бы полезно... Любые мысли?

Ответ 1

Примером может служить эта модель:

public class User
{
    public int UserId { get; set; }
    public string Name { get; set; }
    public ICollection<Role> Roles { get; set; }
}

public class Role
{
    public int RoleId { get; set; }
    public string Description { get; set; }
}

Если вам никогда не интересно загружать всех пользователей, которые находятся в определенной роли, добавив свойство навигации...

public ICollection<User> Users { get; set; }

... в класс Role будут лишними накладными расходами.

Но вы все еще должны EF сказать, что существует отношение "многие ко многим" между User и Role...

modelBuilder.Entity<User>()
            .HasMany(u => u.Roles)
            .WithMany();

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

modelBuilder.Entity<User>()
            .HasMany(u => u.Roles)
            .WithOptional();

Ответ 2

Обратите внимание, что выбор для свойства навигации находится на другой стороне цели.

Посмотрите на пример, хотя этот конкретный случай может быть не идеальным иллюстратором моей точки... Если вы хотите отслеживать математические тесты и повторно использовать вопросы, у вас могут быть две таблицы (Tests и Questions), которые имеют отношение "многие ко многим"; у каждого теста есть несколько вопросов, и каждый вопрос может появиться на нескольких тестах. Тем не менее, вам, возможно, никогда не понадобится собрать коллекцию тестов, на которые будет задан конкретный вопрос - даже если вы знаете, что вопросы могут появляться на нескольких тестах, вас это не интересует. Таким образом, вы используете перегрузку .WithMany() при объявлении этого, так что вы получаете навигационное свойство для получения вопросов теста (theTest.Questions()), но нет навигационного свойства другим способом (theQuestion.Tests()). Но вам все еще нужны отношения "многие-ко-многим", поскольку как тесты, так и вопросы могут иметь многие другие.
Я согласен с тем, что в этом конкретном случае эта установка может не иметь смысла, но, безусловно, есть случаи, когда это происходит, и в этих случаях перегрузка .WithMany() позволяет вам обойтись без определения свойств (и выражения лямбда для каждого из них) вам никогда не понадобится.