代码之家  ›  专栏  ›  技术社区  ›  coolhand

.NET核心集合。添加()从其他对象集合中删除[复制]

  •  -2
  • coolhand  · 技术社区  · 7 年前

    我在stackoverflow中搜索了生成 多对多

    一个简单的场景是:

    public class Person
    {
        public Person() {
            Clubs = new HashSet<Club>();
        }
        public int PersonId { get; set; }
        public virtual ICollection<Club> Clubs { get; set; }
    }
    
    public class Club
    {
        public Club() {
            Persons = new HashSet<Person>();
        }
        public int ClubId { get; set; }
        public virtual ICollection<Person> Persons { get; set; }
    }
    

    请纠正我,如果我错了,但我诚实地找不到一个问题,其中包含了如何使用所描述的工具进行这一操作的详细解释。 有人能解释一下这是怎么做到的吗?

    0 回复  |  直到 7 年前
        1
  •  48
  •   Kirk Larkin    5 年前

    EF核心5.0 RC1+

    对于efcore5.0rc1,不需要显式连接表就可以做到这一点。你可以在没有多个核心的情况下配置多个EF的关系 PersonClub 类型。

    看到了吗 What's New in EF Core 5.0, RC1, Many-to-many

    以前的版本

    here 举个例子。

    issue 在Github上请求无需显式类就可以完成此操作,但尚未完成。

    使用您的场景,我链接的示例将推荐以下实体类:

    public class Person
    {
        public int PersonId { get; set; }
        public virtual ICollection<PersonClub> PersonClubs { get; set; }
    }
    
    public class Club
    {
        public int ClubId { get; set; }
        public virtual ICollection<PersonClub> PersonClubs { get; set; }
    }
    
    public class PersonClub
    {
        public int PersonId { get; set; }
        public Person Person { get; set; }
        public int ClubId { get; set; }
        public Club Club { get; set; }
    }
    

    以下内容 OnModelCreating 然后将用于设置:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<PersonClub>()
            .HasKey(pc => new { pc.PersonId, pc.ClubId });
    
        modelBuilder.Entity<PersonClub>()
            .HasOne(pc => pc.Person)
            .WithMany(p => p.PersonClubs)
            .HasForeignKey(pc => pc.PersonId);
    
        modelBuilder.Entity<PersonClub>()
            .HasOne(pc => pc.Club)
            .WithMany(c => c.PersonClubs)
            .HasForeignKey(pc => pc.ClubId);
    }
    

    如果你觉得需要,一定要去讨论我联系的公开问题,并表达你的沮丧。

    编辑:公开的问题建议使用一个简单的 Select 在这个有点繁琐的层次结构中导航。为了从 PersonId 收藏 Club s、 你可以用 SelectMany

    var clubs = dbContext.People
        .Where(p => p.PersonId == id)
        .SelectMany(p => p.PersonClubs);
        .Select(pc => pc.Club);
    

    我不能担保这是否真的是一个“最佳实践”,但它肯定能起到作用,我认为公平地说它并不过分丑陋。

        2
  •  25
  •   paul van bladel    8 年前

    public class Person
    {
        public int PersonId { get; set; }
        public virtual ICollection<PersonClub> PersonClubs { get; set; }
    }
    
    public class Club
    {
        public int ClubId { get; set; }
        public virtual ICollection<PersonClub> PersonClubs { get; set; }
    }
    
    public class PersonClub
    {
        public int PersonId { get; set; }
        public Person Person { get; set; }
        public int ClubId { get; set; }
        public Club Club { get; set; }
    }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<PersonClub>()
            .HasKey(pc => new { pc.PersonId, pc.ClubId });
    }
    

    所以,配置“粘合表”的块是 如@Kirk示例所示:

    modelBuilder.Entity<PersonClub>()
        .HasOne(pc => pc.Person)
        .WithMany(p => p.PersonClubs)
        .HasForeignKey(pc => pc.PersonId);
    
    modelBuilder.Entity<PersonClub>()
        .HasOne(pc => pc.Club)
        .WithMany(c => c.PersonClubs)
        .HasForeignKey(pc => pc.ClubId);
    
        3
  •  2
  •   Harald Coppoolse    8 年前

    Person 有零或更多 Clubs Club 有零或更多 Persons

    您可能知道关系数据库需要一个额外的表来实现这种多对多关系。实体框架的好处在于它能识别这种关系并为您创建这个额外的表。

    乍一看,这个额外的表不是一个问题 dbSet 在你的 DbContext :“如果没有 DbSet 为了它?”。

    幸运的是,您不需要在查询中提到这个额外的表。

    var result = myDbContext.Persons
        .Where(person => person.Name == "John Doe")
        .Select(person => new
        {
            PersonId = person.Id,
            PersonName = person.Name,
            AttendedCountryClubs = person.Clubs
                .Where(club => club.Type = ClubType.CountryClub),
        };
    

    实体框架将认识到需要一个带有额外多对多表的联接,并且将执行这种联接,而不必提及这个额外的表。

    var result = myDbContext.Clubs
        .Where(club => club.Type = ClubType.CountryClub)
        .Select(club => new
        {
             ClubId = club.Id,
             ClubName = club.Name,
             AnonymousMembers = club.Persons
                 .Where(person => person.Name == "John Doe"),
        }
    

    我曾经经历过,一旦我开始在结果集合中考虑我想要的,而不是获取这些集合所需的联接,我发现我几乎没有使用联接。一对多关系以及多对多关系都是如此。实体框架将在内部使用适当的连接。