Strange Entity Framework Behavior

I have this model class:

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>(); } 

Then I add some records to the database:

 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(); 

Then I run this query:

 var user2 = context.Users.First(user => user.Name == "user2"); foreach (var u in user2.Collection2) Console.WriteLine($"{user2.Name} Collection2 {u.Name}"); 

And I get:

user2 Collection2 user1

Why do I have an entry in Collection2 ? And how to fix it?

UPDATE

enter image description here

This is a link to a test project https://drive.google.com/file/d/0BxP-1gZwSGL5S1c4cWN1Q2NsYVU/view

+6
source share
1 answer

This is not a strange but expected behavior.

Consider the following model:

 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; } } 

This is a typical EF many-to-many association with an implicit join table. When you add entity1 to entity2.Collection1 , it also adds entity2 to entity1.Collection2 .

Now replace Entity1 = Entity2 = User . The result is your model.

Soon, this EF model creates a self many-to-many relationship through an implicit UsersUsers connection UsersUsers , so you get the behavior described.

Since your intent seems to be related to two one-to-many relationships, you should explicitly specify EF using the 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(); } } 

Now everything will work as expected.

+4
source

All Articles