EF Core 关系配置以及反向工程
每日英语:
//I‘m into sports//我喜欢运动 be into sth
I can't believe you're watching that.
The Golf Channel? I'm into golf. //Channel频道 ; 渠道 ; 电视台 ;
Since when?
Since college.I used to play every day.
每日诗词:随机看一篇 没有目的性
五言绝句
行宫
唐代:元稹
寥落古行宫,宫花寂寞红。
白头宫女在,闲坐说玄宗。
译文
曾经富丽堂皇的古行宫已是一片荒凉冷落,宫中艳丽的花儿在寂寞寥落中开放。
幸存的几个满头白发的宫女,闲坐无事只能谈论着玄宗轶事。
注释
寥(liáo)落:寂寞冷落。行宫:皇帝在京城之外的宫殿。这里指当时东都洛阳
的皇帝行宫上阳宫。
宫花:行宫里的花。
白头宫女:据白居易《上阳白发人》,一些宫女天宝末年被“潜配”到上阳宫,
在这冷宫里一闭四十多年,成了白发宫人。
说:谈论。玄宗:指唐玄宗。
EF Core (反向工程)
// Scaffold [ˈskæfəʊld] 脚手架
Scaffold-DbContext ‘Server=.;'Database=demo1;Trusted_Connection=True'
Microsoft.EntityFrameworkCore.SqlServer
作者推荐都是用Code First 但是由于项目有些是已经存在一部分数据库了 先做反向工程生成对应的实体类然后再自己添加或者修改实体类 最终其实还是Code First 模型驱动
每次反向工程都会覆盖之前的文件,(之前修改的代码还会丢失)
T_Cat 数据库中 生成的实体类为TCat 可能我们是需要修改生成的代码的;
总结:如果存在这种项目 第一次整理好数据库之后,进行对应的反向工程之后,对生成的实体类进行维护修改(增加FluentApi 或者Data Annotation),然后后续的操作全部基于Code First流程来。
查看EF Core 对实体类操作生成的对应的sql语句
EF Core 5.0以后不用自己引入日志来打印了 ,EF Core自带日志输出
在对应的XXXXDbContext里面的OnConfiguring方法添加LogTo即可
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
string connStr = "Server=.;Database=demo1;Trusted_Connection=True";
optionsBuilder.UseSqlServer(connStr);
optionsBuilder.LogTo(Console.WriteLine);
}
由于EF Core底层帮我们屏蔽了不同数据库的差异,我们对于不同的数据库的操作代码是一样的,所以生成的sql脚本是不可以直接作用其他数据库的。
Add-Migration -OutputDir //使用这个命令会生成各个不同的数据库的迁移脚本
参考地址:https://docs.microsoft.com/zh-cn/ef/core/managing-schemas/migrations/providers?tabs=dotnet-core-cli
关系配置:
一对多,多对多,一对一
配置模式如下
//A有xxx个B对象,B对象中有YYY个A (xxx,yyy的可选择的数量是One或者Many)
HasXXX().WithYYY();
Delivery实体类以及DeliveryConfig
一对一
class Delivery
{
public long Id { get; set; }
public string CompanyName { get; set; }//快递公司名
public String Number { get; set; }//快递单号
public Order Order { get; set; }//订单
public long OrderId { get; set; }//指向订单的外键
}
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
class DeliveryConfig : IEntityTypeConfiguration<Delivery>
{
public void Configure(EntityTypeBuilder<Delivery> builder)
{
builder.ToTable("T_Deliveries");
builder.Property(d => d.CompanyName).IsUnicode().HasMaxLength(10);
builder.Property(d => d.Number).HasMaxLength(50);
}
}
Order以及OrderConfig
class Order
{
public long Id { get; set; }
public string Name { get; set; }//商品名
public string Address { get; set; }//收货地址
public Delivery? Delivery { get; set; }//快递信息
}
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
class OrderConfig : IEntityTypeConfiguration<Order>
{
public void Configure(EntityTypeBuilder<Order> builder)
{
builder.ToTable("T_Orders");
builder.Property(o => o.Address).IsUnicode();
builder.Property(o => o.Name).IsUnicode();
builder.HasOne<Delivery>(o => o.Delivery).WithOne(d => d.Order)
.HasForeignKey<Delivery>(d => d.OrderId);
}
}
TestDbContext:
using Microsoft.EntityFrameworkCore;
class TestDbContext : DbContext
{
public DbSet<Delivery> Deliveries { get; set; }
public DbSet<Order> Orders { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
string connStr = "Server=.;Database=demo6;Trusted_Connection=True";
optionsBuilder.UseSqlServer(connStr);
optionsBuilder.LogTo(Console.WriteLine);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);
}
}
一对多
Article以及ArticleConfig
public class Article
{
public long Id { get; set; }//主键
public string Title { get; set; }//标题
public string Content { get; set; }//内容
public List<Comment> Comments { get; set; } = new List<Comment>(); //此文章的若干条评论
}
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
class ArticleConfig : IEntityTypeConfiguration<Article>
{
public void Configure(EntityTypeBuilder<Article> builder)
{
builder.ToTable("T_Articles");
builder.Property(a => a.Content).IsRequired().IsUnicode();
builder.Property(a => a.Title).IsRequired().IsUnicode().HasMaxLength(255);
}
}
Comment以及CommentConfig
public class Comment
{
public long Id { get; set; }
public Article Article { get; set; }
public long ArticleId { get; set; }
public string Message { get; set; }
}
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
class CommentConfig : IEntityTypeConfiguration<Comment>
{
public void Configure(EntityTypeBuilder<Comment> builder)
{
builder.ToTable("T_Comments");
builder.HasOne<Article>(c => c.Article).WithMany(a => a.Comments)
.IsRequired().HasForeignKey(c => c.ArticleId);
builder.Property(c => c.Message).IsRequired().IsUnicode();
}
}
TestDbContext
using Microsoft.EntityFrameworkCore;
class TestDbContext : DbContext
{
public DbSet<Article> Articles { get; set; }
public DbSet<Comment> Comments { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
string connStr = "Server=.;Database=demo3;Trusted_Connection=True";
optionsBuilder.UseSqlServer(connStr);
optionsBuilder.LogTo(Console.WriteLine);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);
}
}
多对多
Student以及StudentConfig
class Student
{
public long Id { get; set; }
public string Name { get; set; }
public List<Teacher> Teachers { get; set; } = new List<Teacher>();
}
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
class StudentConfig : IEntityTypeConfiguration<Student>
{
public void Configure(EntityTypeBuilder<Student> builder)
{
builder.ToTable("T_Students");
builder.Property(s => s.Name).IsUnicode().HasMaxLength(20);
builder.HasMany<Teacher>(s => s.Teachers).WithMany(t => t.Students)
.UsingEntity(j => j.ToTable("T_Students_Teachers"));
}
}
Teacher以及TeacherConfig
class Teacher
{
public long Id { get; set; }
public string Name { get; set; }
public List<Student> Students { get; set; } = new List<Student>();
}
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
class TeacherConfig : IEntityTypeConfiguration<Teacher>
{
public void Configure(EntityTypeBuilder<Teacher> builder)
{
builder.ToTable("T_Teachers");
builder.Property(s => s.Name).IsUnicode().HasMaxLength(20);
}
}
TestDbContext
using Microsoft.EntityFrameworkCore;
class TestDbContext : DbContext
{
public DbSet<Student> Students { get; set; }
public DbSet<Teacher> Teachers { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
string connStr = "Server=.;Database=demo7;Trusted_Connection=True";
optionsBuilder.UseSqlServer(connStr);
optionsBuilder.LogTo(Console.WriteLine);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);
}
}
Program:
using Microsoft.EntityFrameworkCore;
using TestDbContext ctx = new TestDbContext();
foreach (var t in ctx.Teachers.Include(t => t.Students))
{
Console.WriteLine($"老师{t.Name}");
foreach (var s in t.Students)
{
Console.WriteLine($"---{s.Name}");
}
}
Include 起到left join 作用
AutoInclude会自动进行include 操作 可能会影响性能,不推荐 感兴趣可以去查看EF Core资料
总结:
HasXXX().WithYYY()理解A有xxx个B对象,B对象中有YYY个A这句话即可 ;
多对多(HasMany,HasMany)在net5.0之前是不能使用的,在5.0之后才能使用
//注意中间表的配置
builder.HasMany<Teacher>(s => s.Teachers).WithMany(t => t.Students)
.UsingEntity(j => j.ToTable("T_Students_Teachers"));
也可参考地址:https://blog.csdn.net/wsnbbdbbdbbdbb/article/details/122270706