C# EF Core 一对一 一对多 多对多 连接查询

外键

什么是外键 百度百科

EF教程

EF教程
EF6(关系)微软官方文档
EF Core(关系)微软官方文档

EF外键约定

外键定义在从表中;
从表外键名字段一般默认为: "主表实体名称+Id";
如果不指定主表字段,从表外键值默认等于主表的值;

建议看官方文档,里面真的很详细.

以下是个人见解

表关联时都会区分主表和从表,主表和从表都有自己的主键(primary key);
主表:不一定会强关联从表,毕竟如人员信息表,很多业务表都用到,不可能在人员信息表里逐一关联;
从表:跟主表一定是强关联的,一定是依赖主表的某一个或多个字段为自身对应的键,也就是外键(foreign key);

一对一

有两个类,User是主表,UserExpand是从表,如下

public class User
{
    public int Id{ get; set; }
    public string Name { get; set; }
}
public class UserExpand{
	public int Id{get;set;}
	public int Age{get;set;}
}

特性标注

public class User
{
    public int Id{ get; set; }
    public string Name { get; set; }
    public UserExpand UserExpand { get; set; }	//看情况而加,加的话可以方便EF Include联查
}
public class UserExpand{
	public int Id{get;set;}
	public int Age{get;set;}
	
	public int UserId{get;set;}
	[ForeignKey(nameof(UserId))]
	public User User{get;set;}
}
或者
public class UserExpand{
	public int Id{get;set;}
	public int Age{get;set;}
	
	[ForeignKey(nameof(User))]
	public int UserId{get;set;}
	public User User{get;set;}
}

Fluent API配置

EF6 默认自动关联,不需要配置;
EF Core 
 public void Configure(EntityTypeBuilder<UserExpand> builder)
        {
            builder.HasKey(e => e.Id);//配置UserExpand 的主键
            
            builder.HasOne<User>(e=>e.User)	//UserExpand有一个(HasOne)User类型的关联,属性是e.User
           		//这个关联类型User(WithOne)跟自己(UserExpand)的关联关系是"有一个"
                .WithOne() //或者 WithOne(e=>e.UserExpand)  如果User 带有UserExpand的时候
                .HasForeignKey(e => e.UserId); //指定与User 关联的外键
        }

一对多

有两个类,Main是主表,Detailed是从表,如下
Detailed也是Main的明细表

public class Main
{
    public Guid Id{ get; set; }
    public string Name { get; set; }
}
public class Detailed{
	public int Id{get;set;}
	public Guid MainId{get;set;}
	public byte[] Data{get;set;}
}

特性标注

public class Main
{
    public Guid Id{ get; set; }
    public string Name { get; set; }
    public virtual ICollection<Detailed> Detaileds{ get; set; }
}
public class Detailed{
	public int Id{get;set;}
	//	[ForeignKey(nameof(Main))] //也可以这样
	public Guid MainId{get;set;}
	public byte[] Data{get;set;}
	[ForeignKey(nameof(MainId))]
	public virtual Main Main{ get; set; }
}

Fluent API配置


 EF6
 //在Detailed表配置
 public class DetailedConfig:EntityTypeConfiguration<Detailed>{
 	public DetailedConfig(){
 		HasKey(e => e.Id);
 		HasRequired<Main>(e=>e.Main)	//Detailed有一个Main类型的Main属性
 		.WithMany(e=>e.Detaileds)	//在Main类型身上有(WithMany)许多个对应的ICollection<Detailed>,属性是Detaileds
 		.HasForeignKey(e=>e.MainId); //指定Detailed对Main的外键是MainId,对应着Main的主键Id
	}
 }
 
EF Core
//与EF6类似的
public void Configure(EntityTypeBuilder<Detailed> builder)
        {
            builder.HasKey(e => e.Id);
            builder.HasOne<Main>(e=>e.Main)
                .WithMany(e=>e.Detaileds)
                .HasForeignKey(e => e.MainId);
        }
//也可以在主表配置
public void Configure(EntityTypeBuilder<Main> builder)
        {
            builder.HasKey(e => e.Id);
            builder.HasMany<Detailed>(e=>e.Detaileds)
                .WithOne(e=>e.Main)
                .HasPrincipalKey(e => e.Id);
        }

多对多

多对多比较特殊点的就是需要依靠中间表
举例如下:Post,Tag,PostTag三个实体

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public ICollection<Tag> Tags { get; set; }
    public List<PostTag> PostTags { get; set; }
}

public class Tag
{
    public string TagId { get; set; }

    public ICollection<Post> Posts { get; set; }
    public List<PostTag> PostTags { get; set; }
}

public class PostTag
{
    public int PostId { get; set; }
    public Post Post { get; set; }

    public string TagId { get; set; }
    public Tag Tag { get; set; }
}

Fluent API配置

 EF6 配置
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Post>()
    .HasMany(t => t.Tags)
    .WithMany(t => t.Posts)
    .Map(m =>
    {
        m.ToTable("PostTag");
        m.MapLeftKey("TagId");
        m.MapRightKey("PostId");
    });
}

 EF Core配置
  protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
    	//直接多对多配置
        modelBuilder.Entity<Post>()
            .HasMany(p => p.Tags)
            .WithMany(p => p.Posts)
            .UsingEntity<PostTag>(
                j => j
                    .HasOne(pt => pt.Tag)
                    .WithMany(t => t.PostTags)
                    .HasForeignKey(pt => pt.TagId),
                j => j
                    .HasOne(pt => pt.Post)
                    .WithMany(p => p.PostTags)
                    .HasForeignKey(pt => pt.PostId),
                j =>
                {
                    j.HasKey(t => new { t.PostId, t.TagId });
                });
		
		//间接多对多配置
		modelBuilder.Entity<PostTag>()
            .HasOne(pt => pt.Post)
            .WithMany(p => p.PostTags)
            .HasForeignKey(pt => pt.PostId);

       	modelBuilder.Entity<PostTag>()
            .HasOne(pt => pt.Tag)
            .WithMany(t => t.PostTags)
            .HasForeignKey(pt => pt.TagId);
    }
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值