实体框架核心:与同一实体的多对多关系

时间:2022-10-05 15:13:46

I am trying to map many-to-many relationship with the same entity. The User entity has an IList<User> data field for Contacts, which stores users' contacts/friends information:

我试图与同一个实体映射多对多关系。用户实体具有用于联系人的IList <用户> 数据字段,用于存储用户的联系人/朋友信息:

public class User : DomainModel
{
    public virtual IList<User> Contacts { get; protected set; }
    //irrelevant code omitted
}

When I try to use fluent API to map this many to many relationship, it gives me some trouble. Apparently, when I use HasMany() on the user.Contacts property, it has no WithMany() method to call next. The intellisense from Visual Studio only shows WithOne(), but not WithMany().

当我尝试使用流畅的API来映射这么多对多的关系时,它给我带来了一些麻烦。显然,当我在user.Contacts属性上使用HasMany()时,它没有WithMany()方法来调用next。 Visual Studio中的intellisense仅显示WithOne(),但不显示WithMany()。

modelBuilder.Entity<User>().HasMany(u => u.Contacts).WithMany() 
// gives compile time error: CS1061 'CollectionNavigationBuilder<User, User>' does not contain a definition for 'WithMany' and no extension method 'WithMany' accepting a first argument of type 

So why does this happen? Is there anything I did wrong to map this many-to-many relationship?

那么为什么会这样呢?有没有什么我做错了映射这种多对多的关系?

2 个解决方案

#1


18  

So why does this happen? Is there anything I did wrong to map this many-to-many relationship?

那么为什么会这样呢?有没有什么我做错了映射这种多对多的关系?

No, you didn't do anything wrong. It's just not supported. Current status here.

不,你没有做错任何事。它只是不受支持。目前的状态。

Many-to-many relationships without an entity class to represent the join table are not yet supported. However, you can represent a many-to-many relationship by including an entity class for the join table and mapping two separate one-to-many relationships.

尚不支持没有实体类来表示连接表的多对多关系。但是,您可以通过包含连接表的实体类并映射两个单独的一对多关系来表示多对多关系。

With EF-Core you should create the entity for the mapping table. Such as UserContacts. A complete example in the docs, as mentioned in the comments. I haven't actually tested the code below, but it should look something like this:

使用EF-Core,您应该为映射表创建实体。比如UserContacts。如评论中所述,文档中的完整示例。我实际上没有测试下面的代码,但它应该看起来像这样:

public class UserContacts
{
    public int UserId { get; set; } 
    public virtual User User { get; set; }

    public int ContactId { get; set; } // In lack of better name.
    public virtual User Contact { get; set; }
}

public class User : DomainModel
{
    public List<UserContacts> Contacts { get; set; }
}

And your modelBuilder.

和你的modelBuilder。

  modelBuilder.Entity<UserContacts>()
        .HasOne(pt => pt.Contact)
        .WithMany(p => p.Contacts)
        .HasForeignKey(pt => pt.ContactId);

    modelBuilder.Entity<UserContacts>()
        .HasOne(pt => pt.User)
        .WithMany(t => t.Contacts)
        .HasForeignKey(pt => pt.UserId);

#2


1  

May be I am late here but @smokesnes, answer will not work for many to many relationship for the same entity up to entity framework version 2.1. But his answer will work fine for the many to many relationship with different entity.

可能是我迟到了,但@smokesnes,答案对于同一实体到实体框架版本2.1的多对多关系不起作用。但他的答案对于与不同实体的多对多关系会很好。

Here is the solution for many to many relationship for the same entity(up to EF Core 2.1)

以下是同一实体(多达EF Core 2.1)的多对多关系的解决方案

public class UserContacts
{
    public int UserId { get; set; } 
    public virtual User User { get; set; }

    public int ContactId { get; set; } 
    public virtual User Contact { get; set; }
}

public class User : DomainModel
{
    public List<UserContacts> UserContacts { get; set; }
    public List<UserContacts> ContactUsers { get; set; }
}

Then in the model builder:

然后在模型构建器中:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
   base.OnModelCreating(modelBuilder);

    modelBuilder.Entity<UserContacts>()
    .HasOne(pt => pt.User)
    .WithMany(p => p.UserContacts)
    .HasForeignKey(pt => pt.UserId);

    modelBuilder.Entity<UserContacts>()
    .HasOne(pt => pt.Contact)
    .WithMany(t => t.ContactUsers)
    .HasForeignKey(pt => pt.ContactId);
}

#1


18  

So why does this happen? Is there anything I did wrong to map this many-to-many relationship?

那么为什么会这样呢?有没有什么我做错了映射这种多对多的关系?

No, you didn't do anything wrong. It's just not supported. Current status here.

不,你没有做错任何事。它只是不受支持。目前的状态。

Many-to-many relationships without an entity class to represent the join table are not yet supported. However, you can represent a many-to-many relationship by including an entity class for the join table and mapping two separate one-to-many relationships.

尚不支持没有实体类来表示连接表的多对多关系。但是,您可以通过包含连接表的实体类并映射两个单独的一对多关系来表示多对多关系。

With EF-Core you should create the entity for the mapping table. Such as UserContacts. A complete example in the docs, as mentioned in the comments. I haven't actually tested the code below, but it should look something like this:

使用EF-Core,您应该为映射表创建实体。比如UserContacts。如评论中所述,文档中的完整示例。我实际上没有测试下面的代码,但它应该看起来像这样:

public class UserContacts
{
    public int UserId { get; set; } 
    public virtual User User { get; set; }

    public int ContactId { get; set; } // In lack of better name.
    public virtual User Contact { get; set; }
}

public class User : DomainModel
{
    public List<UserContacts> Contacts { get; set; }
}

And your modelBuilder.

和你的modelBuilder。

  modelBuilder.Entity<UserContacts>()
        .HasOne(pt => pt.Contact)
        .WithMany(p => p.Contacts)
        .HasForeignKey(pt => pt.ContactId);

    modelBuilder.Entity<UserContacts>()
        .HasOne(pt => pt.User)
        .WithMany(t => t.Contacts)
        .HasForeignKey(pt => pt.UserId);

#2


1  

May be I am late here but @smokesnes, answer will not work for many to many relationship for the same entity up to entity framework version 2.1. But his answer will work fine for the many to many relationship with different entity.

可能是我迟到了,但@smokesnes,答案对于同一实体到实体框架版本2.1的多对多关系不起作用。但他的答案对于与不同实体的多对多关系会很好。

Here is the solution for many to many relationship for the same entity(up to EF Core 2.1)

以下是同一实体(多达EF Core 2.1)的多对多关系的解决方案

public class UserContacts
{
    public int UserId { get; set; } 
    public virtual User User { get; set; }

    public int ContactId { get; set; } 
    public virtual User Contact { get; set; }
}

public class User : DomainModel
{
    public List<UserContacts> UserContacts { get; set; }
    public List<UserContacts> ContactUsers { get; set; }
}

Then in the model builder:

然后在模型构建器中:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
   base.OnModelCreating(modelBuilder);

    modelBuilder.Entity<UserContacts>()
    .HasOne(pt => pt.User)
    .WithMany(p => p.UserContacts)
    .HasForeignKey(pt => pt.UserId);

    modelBuilder.Entity<UserContacts>()
    .HasOne(pt => pt.Contact)
    .WithMany(t => t.ContactUsers)
    .HasForeignKey(pt => pt.ContactId);
}