程序问答   发布时间:2022-06-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了EF Core 自身之间的关系映射 测试 1测试 2大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决EF Core 自身之间的关系映射 测试 1测试 2?

开发过程中遇到EF Core 自身之间的关系映射 测试 1测试 2的问题如何解决?下面主要结合日常开发的经验,给出你关于EF Core 自身之间的关系映射 测试 1测试 2的解决方法建议,希望对你解决EF Core 自身之间的关系映射 测试 1测试 2有所启发或帮助;

背景

假设数据库中有两个表

@H_116_7@member

ID 姓名
1 托尼
2 史蒂夫
3 布鲁斯
4 斯科特

@H_116_7@memberRecruit

会员编号 RecruitmentMemberID
1 2
1 3
2 4

RecruitmentMemberID 就是 @H_116_7@memberID

还有两个类

public class Member
{
   public int id { get; set; }
   public String name { get; set; }
   public IList<MemberRecruit> Recruits { get; set; }
}

public class MemberRecruit
{
   public int MemberID { get; set; }
   public int RecruitmentMemberID { get; set; }
}

使用 EF Core 3.1,可以轻松地在 DbContext 中为 Ownsmany 创建 @H_116_7@member.Recuits 关系,例如

builder.Entity<Member>(m =>
{
    m.@R_10_10586@ble("Member","dbo");

    m.HasKey(x => x.MemberID);

    m.Ownsmany(x => x.Recruits,nav =>
    {
        nav.@R_10_10586@ble("MemberRecruit","dbo");
        nav.HasKey(x => new
        {
            x.MemberID,x.RecruitmentMemberID
        });
        nav.Withowner().HasForeignKey(x => x.MemberID);
    });
});

问题

如果我想将类结构更改为类似

public class Member
{
   public int id { get; set; }
   public String name { get; set; }
   public IList<MemberRecruit> Recruits { get; set; }
}

public class MemberRecruit
{
   public int MemberID { get; set; }
   public int RecruitmentMemberID { get; set; }
   public Member Recruitment { get; set; } // This is the recruited member
}

在不更改表的情况下,是否有一种很好的做法可以使用 Owns.HasOne.WithMany + .Hasmany.WithOne 关系在 DbContext 中使用 FluentAPI 映射它,以便当我有 DbSet<Member> Members 时,我可以像这样查询以下?

var recruitments = (await _db.Members.AsnoTrack()
                             .Include(x => x.Recruits)
                             .FirstOrDefaultAsync(x => x.ID == request.ID,token))
                          .Recruits
                          .SELEct(x => x.Recruitment,token);
return recruitments.SELEct(x => (x.ID,x.Name));
// if request.ID is 1,return will be [(2,"Steve"),(3,"Bruce")]
// if request.ID is 2,return will be [(4,"Scott")]
// if request.ID is 3,return will be []

或者用同样的两张表,映射下面的类

public class Member
{
   public int id { get; set; }
   public String name { get; set; }
   public IList<Member> Recruitments { get; set; }
}

这样查询就可以简化为

var member = await _db.Members.AsnoTrack()
                               .Include(x => x.Recruitments)
                               .FirstOrDefaultAsync(x => x.ID == request.ID,token);
return member.Recruitments.SELEct(x => (x.ID,x.Name));

我尝试过的

测试 1

builder.Entity<Member>(m =>
{
    m.@R_10_10586@ble("Member",x.RecruitmentMemberID
        });
        nav.Withowner().HasForeignKey(x => x.MemberID);

        nav.HasOne(x => x.Member) // Added HasOne.WithMany
           .WithMany(x => x.Recruits)
           .HasForeignKey(x => x.RecruitmentMemberID);
    });
});

这次回归

var member = await _db.Members.AsnoTrack()
                      .Include(x => x.Recruits)
                      .FirstOrDefaultAsync(x => x.ID == 1,token);
// member.Recurits.Count is 1 instead of 2
// member.Recurits[0].Recruitment.ID is 1 which is incorrect
@H_197_149@测试 2
builder.Entity<Member>(m =>
{
    m.@R_10_10586@ble("Member",x.RecruitmentMemberID
        });
        nav.Withowner().HasForeignKey(x => x.MemberID);

        nav.HasOne(x => x.Member)
           .WithMany(x => x.Recruits)
           .HasForeignKey(x => x.MemberID); // Change the foreign key
    });
});

这次回归

var member = await _db.Members.AsnoTrack()
                      .Include(x => x.Recruits)
                      .FirstOrDefaultAsync(x => x.ID == 1,token);
// member.Recurits.Count is 2 which is correct
// member.Recurits.SELEct(x => x.Recruitment.ID) are all 1 which is incorrect

解决方法

为您的课程添加关系

    public partial class Member
    {
        public Member()
        {
            MemberMembers = new HashSet<MemberRecruit>();
            MemberRecruits = new HashSet<MemberRecruit>();
        }

        [Key]
        public int id { get; set; }
        public String Name { get; set; }

       

        [InverseProperty(nameof(MemberRecruit.Member))]
        public virtual ICollection<MemberRecruit> MemberRecruits { get; set; }

        [InverseProperty(nameof(MemberRecruit.Recruit))]
        public virtual ICollection<MemberRecruit> MemberMembers { get; set; }
    }
        public partial class MemberRecruit
        {
            [Key]
            public int id { get; set; }
            public int RecruitId { get; set; }
            public int MemberId { get; set; }

            [ForeignKey(nameof(MemberId))]
            [InverseProperty("MemberRecruits")]
            public virtual Member Member { get; set; }

            [ForeignKey(nameof(RecruitId))]
            [InverseProperty("MemberMembers")]
            public virtual Member Recruit { get; set; }
        }

和 dbcontext

        public virtual DbSet<Member> Members{ get; set; }
        public virtual DbSet<MemberRecruit> MemberRecruits { get; set; }

        protected override void OnModelCreaTing(ModelBuilder modelBuilder)
        {
          modelBuilder.Entity<MemberRecruit>(entity =>
            {
                entity.HasOne(d => d.Member)
                    .WithMany(p => p.MemberRecruits)
                    .HasForeignKey(d => d.MemberId)
                    .ondelete(deleteBehavior.ClientSetnull);


                entity.HasOne(d => d.Recruit)
                    .WithMany(p => p.MemberMembers)
                    .HasForeignKey(d => d.RecruitId);

            });

由于任何成员都可能是另一个成员的新成员和另一个新成员的成员,因此它有 2 个虚拟集合 - 1 个显示他是另一个新成员的记录(在 memberId 部分),第二个显示他是另一个新成员的记录招募另一个成员(在recruitId 部分)。因此,如果您想查看会员的所有招聘人员,您可以通过两种方式进行

var recruiters=context.MemberRecruits
.Where(i=> i.MemberId==memberId)
.SELEct(i=>i.Recruit)
.ToList();
//or 
var recruits = _context.Members
.Where(i => i.Id == memberId)
.SELEct(i => i.MemberRecruits.SELEct(j => j.Recruit)).FirstOrDefault();

第二个查询看起来有点奇怪,但您应该明白,members 的意思是 member 是 member,recruss - where member 是招聘人员。也许更好地重命名集合“AsMember”和“AsRecruiter”。由你决定。 由于查询 MemberRecruit 容易得多,我建议使用它进行查询。 另一个例子。 memberId 是招聘人员的成员

var members=context.MemberRecruits
.Where(i=> i.RecruitEID==memberId)
.SELEct(i=>i.Member)
.ToList();
,

如果您想使用第二个选项,根据 MS Docs Single navigation property,您可以通过使用 Fluent API 定义这样的关系来设置导航属性。

给定以下类

public class Member
{
   public int id { get; set; }
   public String Name { get; set; }
   public IList<Member> Recruitments { get; set; }
}
protected override void OnModelCreaTing(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Member>()
        .Hasmany(b => b.Member)
        .WithOne();
}

更新

给定以下类

public class Member
{
   [Key]
   public int id { get; set; }
   public String Name { get; set; }
   public IList<MemberRecruit> Recruitments { get; set; }
}

public class MemberRecruit
{
   [Key]
   public int id { get; set; }
   public int RecruitmentMemberId { get; set; }
   public Member RecruitmentMember { get; set; }
}
protected override void OnModelCreaTing(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Member>()
        .Hasmany(b => b.MemberRecruit)
        .WithOne();

    modelBuilder.Entity<MemberRecruit>()
        .HasOne(b => b.RecruitmentMember)
        .WithOne();
}

你应该可以这样查询

var memeber = context.Member
              .Include(x => x.Recruitments)
              .FirstOrDefaultAsync(x => x.Id == request.Id);

var memberRecruitments = member.Recruitments
                         .SELEct(x => new Member 
                         {
                              Id = x.Id,Name = x.Name 
                         }).ToList();
,

不确定这是否是最佳做法,但以下有效

public class Member
{
   public int id { get; set; }
   public String Name { get; set; }
   public IList<MemberRecruit> Recruits { get; set; }
}

public class MemberRecruit
{
   public int MemberId { get; set; }
   public int RecruitmentMemberId { get; set; }
   public Member Recruitment { get; set; } // This is the recruited member
}

数据库上下文

builder.Entity<Member>(m =>
{
    m.@R_10_10586@ble("Member","dbo");
    m.HasKey(x => x.Id);

    m.Hasmany(x => x.Recruits)
        .WithOne()
        .HasForeignKey(mr => mr.MemberId);
});

builder.Entity<MemberRecruit>(m =>
{
    m.@R_10_10586@ble("MemberRecruit","dbo");
    m.HasKey(x => new
    {
        x.MemberId,x.RecruitmentMemberId
    });

    m.HasOne(x => x.Recruitment)
        .WithOne()
        .HasForeignKey<Member>(x => x.Id)
        .HasPrincipalKey<MemberRecruit>(x => x.RecruitmentMemberId);
});

查询和结果

var member = await _db.Members
                .AsnoTracking()
                .Include(x => x.Recruits)
                .ThenInclude(x => x.Recruitment)
                .FirstOrDefaultAsync(x => x.Id == request.Id,token);
// If request.Id == 1
// member.Recruits.Count is 2
// member.Recruits[0].Recruitment will be (2,"Steve")
// member.Recruits[1].Recruitment will be (3,"Bruce")

大佬总结

以上是大佬教程为你收集整理的EF Core 自身之间的关系映射 测试 1测试 2全部内容,希望文章能够帮你解决EF Core 自身之间的关系映射 测试 1测试 2所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。