参考文档 www.entityframeworktutorial.net/code-first/…
一环境搭建
1 创建一个控制台项目 。
2 添加依赖。
<ItemGroup>
<PackageReference Include="EntityFramework" Version="6.4.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.7">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.7">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="6.0.2" />
</ItemGroup>
3 创建DbContext 类。填写数据库连接。
using Microsoft.EntityFrameworkCore;
namespace EF1.Models;
public class MyDbContext:DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
string? conn = "server=localhost;port=3306;uid=root;pwd=123456;database=ef_study";
var serverVersion = ServerVersion.AutoDetect(conn);
optionsBuilder.UseMySql(conn, serverVersion);
}
}
第一阶段,优先实现走通,后期处理,读配置,ioc 等 。
二 实现最简单的Code First
2.1 创建实现类
namespace EF1.Models
{
public class Dog
{
public long Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
}
DbContext 中添加
DbSet<Dog>? Dog { get; set; }
2.2 生成迁移,执行迁移。
小技巧,数据库示update 之前,发现代码有问题。
运行 dotnet ef migrations remove 进行回滚。
三 自定义字段,表名,索引等
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel;
namespace EF1.Models
{
[Table("t_dog")]
public class Dog2
{
[Column("id")]
[MaxLength(11)]
public long Id { get; set; }
[Index] //加索引
[Column("tname")]
[MaxLength(32)]
[Required]
public string? Name { get; set; }
[Column("age")]
[Description("年龄")]
public int? Age { get; set; }
[Column("created_at")]
public DateTime? CreatedAt { get; set; }
}
}
//Context 中添加DbSet
DbSet<Dog2>? Dog2 { get; set; }
//console 运行脚本
dotnet ef Migrations add dog2
dotnet ef database update
四 处理 1 对1 ,1对多,多对多。
4.1 1 对 1 的例子。
using System.ComponentModel.DataAnnotations.Schema;
namespace EF1.Models
{
[Table("t_stu")]
public class Student
{
public int Id { get; set; }
public string StudentName { get; set; }
public int AddrId { get; set; }
public virtual StudentAddress Address { get; set; }
}
[Table("t_stu_addr")]
public class StudentAddress
{
[ForeignKey("Student")]
public int Id { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public int Zipcode { get; set; }
public string State { get; set; }
public string Country { get; set; }
public virtual Student Student { get; set; }
}
}
运行脚本后。
通常见于大小表套路。 (用户登录表 - 用户信息表) 小表登录,大表拿数据。
4.2 1 对多的例子
最简写法。 外键为GradeId
public class Stu2
{
public int Id { get; set; }
public string Name { get; set; }
public Grade Grade { get; set; }
}
public class Grade
{
public int GradeId { get; set; }
public string GradeName { get; set; }
public string Section { get; set; }
}
自定义外键列名写法。
public class Stu4
{
public int Id { get; set; }
public string Name { get; set; }
[Column("grade_id")]
public int GradeId { get; set; }
public Grade Grade { get; set; }
}
4.3 多对多的例子。
public class Stu
{
public Stu()
{
this.Courses = new HashSet<Course>();
}
public int Id { get; set; }
[Required]
public string StudentName { get; set; }
public virtual ICollection<Course> Courses { get; set; }
}
public class Course
{
public Course()
{
this.Students = new HashSet<Stu>();
}
public int Id { get; set; }
public string CourseName { get; set; }
public virtual ICollection<Stu> Students { get; set; }
}
系统会默认创建关系表。
当需要定制的时候
public class StuConfig : IEntityTypeConfiguration<Stu>
{
public void Configure(EntityTypeBuilder<Stu> builder)
{
builder.ToTable("t_stus");
builder.HasMany<Teacher>(s => s.Teachers).WithMany(t => t.Stus).UsingEntity(j => j.ToTable("t_stu_teacher"));
}
}
public class TeacherConfig : IEntityTypeConfiguration<Teacher>
{
public void Configure(EntityTypeBuilder<Teacher> builder)
{
builder.ToTable("t_teachers");
}
}
记住,一定要DbContext 加上。(方便配置生效)
更进一步,自定义字段名。
public class StuConfig : IEntityTypeConfiguration<Stu>
{
public void Configure(EntityTypeBuilder<Stu> builder)
{
builder.ToTable("t_stus");
builder.HasMany<Teacher>(s => s.Teachers).WithMany(t => t.Stus).UsingEntity(j =>
{
// j.Property
j.ToTable("t_stu_teacher");
j.Property("StusId").HasColumnName("stu_id");
j.Property("TeachersId").HasColumnName("teacher_id");
});
}
}
更多细节 ,需要学会使用fluentApi .
总结,确实有些门槛,你得熟悉套路,手册上的例子,要把代码写死在 DbContext 中。 折腾成如例子那样,捅窗户纸成本非常的高。