EFCore 学习 一 (环境搭建+ codeFirst 建表)

145 阅读2分钟

参考文档 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>

image.png

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 生成迁移,执行迁移。

image.png

image.png

小技巧,数据库示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

image.png

四 处理 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; }
    }
}

运行脚本后。

image.png

通常见于大小表套路。 (用户登录表 - 用户信息表) 小表登录,大表拿数据。

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; }
    }

image.png

自定义外键列名写法。

    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; }
    }

image.png

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; }
    }

系统会默认创建关系表。

image.png

当需要定制的时候


    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 中。 折腾成如例子那样,捅窗户纸成本非常的高。