Странное поведение Entity Framework

#c# #.net #entity-framework

#c# #.net #entity-framework

Вопрос:

У меня есть этот класс модели:

 public class User
{
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection<User> Collection1 { get; set; } = new List<User>();
    public virtual ICollection<User> Collection2 { get; set; } = new List<User>();
}
 

Затем я добавляю несколько записей в базу данных:

 var context = new UsersContext();

var user1 = new User();
var user2 = new User();
var user3 = new User();

user1.Name = "user1";
user2.Name = "user2";
user3.Name = "user3";

user1.Collection1.Add(user2);
user2.Collection1.Add(user3);

context.Users.Add(user1);
context.Users.Add(user2);
context.Users.Add(user3);

context.SaveChanges();
 

Затем я запускаю этот запрос:

 var user2 = context.Users.First(user => user.Name == "user2");

foreach (var u in user2.Collection2)
    Console.WriteLine($"{user2.Name}  Collection2 {u.Name}");
 

И я получаю:

пользователь2 Коллекция2 пользователь1

Почему Collection2 у меня есть запись? И как это исправить?

Обновить.

введите описание изображения здесь

Это ссылка на тестовый проект https://drive.google.com/file/d/0BxP-1gZwSGL5S1c4cWN1Q2NsYVU/view

Комментарии:

1. Вопрос не ясен. Вы имеете в виду, почему существует запись или почему запись ‘user1’?

2. На самом деле интересное поведение. Похоже, у EF есть many-to-many отношение настройки для вас. Вы можете убедиться в этом, просмотрев сгенерированные таблицы.

3. @peval27, извините за мой английский. Почему в collection2 есть запись? Я его не добавлял.

4. @Lightness Я считаю, что объявление его как виртуальной коллекции означает неявную ссылку на таблицу пользователей с именем Collection2. Проверьте таблицы, созданные в БД

5. Пожалуйста, посмотрите на мой проект. Вы увидите, в чем проблема. drive.google.com/file/d/0BxP-1gZwSGL5S1c4cWN1Q2NsYVU /…

Ответ №1:

Это не странно, а ожидаемое поведение.

Рассмотрим следующую модель:

 public class Entity1
{
    public int Id { get; set; }
    public ICollection<Entity2> Collection2 { get; set; }
}

public class Entity2
{
    public int Id { get; set; }
    public ICollection<Entity1> Collection1 { get; set; }
}
 

Это типичная many-to-many связь EF с неявной таблицей соединений. Когда вы добавляете entity1 to entity2.Collection1 , он также добавляет entity2 to entity1.Collection2 .

Теперь замените Entity1 = Entity2 = User . Результатом является именно ваша модель.

Вкратце, с помощью этой модели EF создает собственные many-to-many отношения через неявную UsersUsers таблицу соединений, вот почему вы получаете описанное поведение.

Поскольку ваше намерение, похоже, имеет два one-to-many отношения, вам нужно явно сообщить об этом EF, используя Fluent API:

 public class UsersContext : DbContext
{
    public DbSet<User> Users { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>().HasMany(e => e.Collection1).WithOptional();
        modelBuilder.Entity<User>().HasMany(e => e.Collection2).WithOptional();
    }
}
 

Теперь все будет работать так, как ожидалось.

Комментарии:

1. Отличное объяснение 1 🙂