实体框架的奇怪行为

Lig*_*ess 6 .net c# 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>();
}
Run Code Online (Sandbox Code Playgroud)

然后我在数据库中添加一些记录:

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();
Run Code Online (Sandbox Code Playgroud)

然后我运行这个查询:

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

foreach (var u in user2.Collection2)
    Console.WriteLine($"{user2.Name}  Collection2 {u.Name}");
Run Code Online (Sandbox Code Playgroud)

我得到:

user2 Collection2 user1

为什么Collection2我有记录?以及如何解决它?

UPDATE.

在此输入图像描述

这是测试项目的链接https://drive.google.com/file/d/0BxP-1gZwSGL5S1c4cWN1Q2NsYVU/view

Iva*_*oev 4

这并不奇怪,而是预期的行为。

考虑以下模型:

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; }
}
Run Code Online (Sandbox Code Playgroud)

这是带有隐式连接表的典型 EFmany-to-many关系。当您添加entity1到时entity2.Collection1,它也会添加entity2entity1.Collection2

现在替代Entity1 = Entity2 = User. 结果正是您的模型。

很快,EF 通过该模型many-to-many通过隐式创建自我关系UsersUsers联结表创建自关系,这就是您获得所描述的行为的原因。

由于您的意图似乎有两个one-to-many关系,因此您需要使用 Fluent API 明确告知 EF:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在一切都会按预期进行。