一、关系配置的套路
EFCore中配置的套路
HasXXX(…).WithXXX(…);
XXX有One与Many两个选项,
HasOne(…).WithMany(…);一对多
HasOne(…).WithOne(…);一对一
HasMany(…).WithMany(…);多对多
例:HasOne(a).WithMany(b);
可以理解为,这个实体有一个a,这个a有多个b
二、一对多
1.创建实体
1.Article (一)
class Article
{
public long Id { get; set; }
public string Title { get; set; }
public string Message { get; set; }
//这里加入了导航属性,一篇文章有多个评论
public List<Comment> Comments { get; set; } = new List<Comment>();
}
2.Comment(多)
class Comment
{
public long Id { get; set; }
public string Message { get; set; }
//导航属性,一条评论对应一篇文章
public Article TheArticle { get; set; }
}
2.实体配置
ArticleConfig.cs
class ArticleConfig : IEntityTypeConfiguration<Article>
{
public void Configure(EntityTypeBuilder<Article> builder)
{
//设置表名
builder.ToTable("T_Articles");
//设置Title属性
builder.Property(a => a.Title).HasMaxLength(100).IsUnicode().IsRequired();
//设置Message
builder.Property(a=>a.Message).IsUnicode().IsRequired();
}
}
CommentConfig.cs
class CommentConfig : IEntityTypeConfiguration<Comment>
{
public void Configure(EntityTypeBuilder<Comment> builder)
{
builder.ToTable("T_Comments");
builder.Property(a => a.Message).IsUnicode().IsRequired();
//这里是对两个关系的配置
//意思为comment这个实体有一个TheArticle属性,这个属性对应一个Article实体,而Article实体对应了多个Comment实体
builder.HasOne<Article>(a => a.TheArticle).WithMany(a => a.Comments).IsRequired();
}
}
DbContext的配置
class RealtionDBContext:DbContext
{
private static ILoggerFactory loggerFactory = LoggerFactory.Create(b => b.AddConsole());
public DbSet<Article> Articles { get; set; }
public DbSet<Comment> Comments { get; set; }
//这里是配置
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
//DbContextOptionsBuilder注入
base.OnConfiguring(optionsBuilder);
//设置连接字符串
optionsBuilder.UseSqlServer("server=localhost;uid=sa;pwd=123456;database=demo9_Relations;");
optionsBuilder.UseLoggerFactory(loggerFactory);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//注入ModelBuilder
base.OnModelCreating(modelBuilder);
//获取当前程序集默认的是查找所有继承了IEntityTypeConfiguration的类
modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);
}
}
3.迁移
1.查看表关系
Commnent
Article
看到外键关系已经建立
4.控制台进行数据操作
static void Main(string[] args)
{
using(RealtionDBContext ctx = new RealtionDBContext())
{
Article a1 = new Article();
a1.Title = "LTY就职了";
a1.Message = "据报道...";
Comment c1 = new Comment();
c1.Message = "恭喜";
Comment c2 = new Comment { Message = "厉害啊" };
//这里将Comment的加入到Aritcle中
a1.Comments.Add(c1);
a1.Comments.Add(c2);
//然后在向数据库添加Aritcle(a1)
ctx.Articles.Add(a1);
//更新数据库
ctx.SaveChanges();
}
}
5.关系依赖添加
那么为什么没有添加Comment呢,因为当我们把评论加入到文章中的时候,EFCore会通过我们设置的关系,自动添加到Comment中。
二、一对一
1.实体属性
在一对一中,必须在一方显示设置外键,因为这个外键,可以在两边选,EFCore不清楚在哪边设置,所以需要显示设置
2.配置关系
三、多对多
多对多(HasMany,HasMany)在net5.0之前是不能使用的,在5.0之后才能使用
文章实体
class Article
{
public long Id { get; set; }
public string Title { get; set; }
public string Message { get; set; }
//假设,一篇文章对应多个评论
public List<Comment> Comments { get; set; } = new List<Comment>();
}
class ArticleConfig : IEntityTypeConfiguration<Article>
{
public void Configure(EntityTypeBuilder<Article> builder)
{
builder.ToTable("T_Articles");
builder.Property(a => a.Title).HasMaxLength(100).IsUnicode().IsRequired();
builder.Property(a=>a.Message).IsUnicode().IsRequired();
//UsingEntity用来创建多对多的中间表
builder.HasMany<Comment>(a => a.Comments).WithMany(a => a.Articles).UsingEntity(j=>j.ToTable("T_Articles_Comments"));
}
}
Comment实体
class Comment
{
public long Id { get; set; }
public string Message { get; set; }
//多个评论对应多个文章
public List<Article> Articles { get; set; } = new List<Article>();
}
Comment配置
class CommentConfig : IEntityTypeConfiguration<Comment>
{
public void Configure(EntityTypeBuilder<Comment> builder)
{
builder.ToTable("T_Comments");
builder.Property(a => a.Message).IsUnicode().IsRequired();
}
}
这里创建的中间表T_Articles_Comments由EF自动管理,我们不需要管理中间表