简体   繁体   中英

Strange behavior of Entity Framework

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 a few records in 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 in Collection2 do I have a record? And how to fix it ?

UPDATE.

在此处输入图片说明

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

It's not 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 relationship with implicit junction table. When you add entity1 to entity2.Collection1 , it also adds entity2 to entity1.Collection2 .

Now substitute Entity1 = Entity2 = User . The result is exactly your model.

Shortly, with that model EF creates self many-to-many relationship via implicit UsersUsers junction table, that's why you get the described behavior.

Since your intention seems to be having two one-to-many relations, you need to tell that explicitly to EF by using 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM