它是微软官方发布的基于ADO.NET的ORM框架。通过EF可以很方便地将表映射到实体对象或将实体对象转换为数据库表。
ORM:将数据存储从域对象自动映射到关系型数据库的工具。ORM主要包括3个部分:域对象、关系数据库对象、映射关系。ORM使类提供自动化CRUD,使开发人员从数据库API和SQL中解放出来。
EFCore有2种开发模式:
1. 从数据库生成Class实体类(DataFirst);
2. 由实体类生成数据库表结构(CodeFirst);
EFCore主要特点:
1. 支持多种数据库:SQLServer、MySQL、SQLite等。
2. 支持LINQ查询
3. 支持迁移,当EFCore模型更改时通过几条命令即可转换为数据库表
4. 支持原生sql语句,面对复杂查询性能欠佳时可以使用原生sql进行查询
一、通过EF Core创建数据库表
一般采用代码优先(CodeFirst)的方式,需要先编写实体类,再生成数据库表。
1. 创建实体类
1.1 FluentAPI方式创建(推荐)
先创建实体类再对实体类进行配置
internal class Book
{public long Id { get; set; }/// <summary>/// 标题/// </summary>public string Title { get; set; }/// <summary>/// 发布日期/// </summary>public DateTime PubTime { get; set; }/// <summary>/// 单价/// </summary>public Double Price { get; set; }/// <summary>/// 作者名字/// </summary>public string AuthorName { get; set; }
}
创建一个实现了IEntityTypeConfiguration接口的实体类的配置类BookEntityConfig,它用于配置实体类和数据库表的对应关系
// 使用此接口指定要对哪个实体类进行配置
internal class BookEntityConfig : IEntityTypeConfiguration<Book>
{//对实体类和数据库表的关系进行详细配置public void Configure(EntityTypeBuilder<Book> builder){//设置表名builder.ToTable("T_Books");//设置Title字段最大值为50,并不能为空builder.Property(e => e.Title).HasMaxLength(50).IsRequired();builder.Property(e => e.AuthorName).HasMaxLength(20).IsRequired();}
}
1.2 通过数据注解的方式配置实体类
如果使用数据注解方式配置实体类,直接在定义类中的属性时,配置相应的注解即可。
public class Student
{[Key]public long Id { get; set; }[MaxLength(50)][Unicode][Required]public string Name { get; set; }[MaxLength(50)][Unicode][Required]public string Class { get; set; }public int Age { get; set; }[MaxLength(50)][Unicode][Required]public string Sex { get; set; }
}
2. 创建DbContext
创建实体类之后,需要创建继承自DbContext类的上下文类,并添加DbSet<实体>属性,该属性用于后续对表的操作。
internal class TestDbContext:DbContext
{//定义实体类属性,后续增删改查都用此对象public DbSet<Book> Books { get; set; }protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){//配置连接数据库字符串string connStr = "Data Source=REDMIBOOKPRO15\\SQL;Initial Catalog=EFCore;Integrated Security=True;Trust Server Certificate=True";//指定使用SqlServer数据库进行连接optionsBuilder.UseSqlServer(connStr);}protected override void OnModelCreating(ModelBuilder modelBuilder){base.OnModelCreating(modelBuilder);//加载当前程序集中所有实现了IEntityTypeConfiguration接口的类modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);}
}
3. 通过实体类生成数据库表
安装Microsoft.EntityFrameworkCore.Tools包
1. 在【程序包管理器控制台】中执行如下命令:Add-Migration InitialCreate InitialCreate:给这次迁移取的名字


二、EF Core的增删改查
1. 插入数据
using efCore;
//创建上下文对象,并使用using自动释放资源
using TestDbContext ctx = new TestDbContext();
//创建book对象数据
var b1 = new Book
{AuthorName = "杨中科",Title = "零基础趣学C语言",Price = 59.8,PubTime = new DateTime(2019, 3, 1)
};
var b2 = new Book
{AuthorName = "Robert Sedgewick",Title = "算法(第4版)",Price = 99,PubTime = new DateTime(2012, 10, 1)
};
var b3 = new Book
{AuthorName = "吴军",Title = "数学之美",Price = 69,PubTime = new DateTime(2020, 5, 1)
};
var b4 = new Book
{AuthorName = "杨中科",Title = "程序员的SQL金典",Price = 52,PubTime = new DateTime(2008, 9, 1)
};
var b5 = new Book
{AuthorName = "吴军",Title = "文明之光",Price = 246,PubTime = new DateTime(2017, 3, 1)
};
//添加数据
ctx.Books.Add(b1);
ctx.Books.Add(b2);
ctx.Books.Add(b3);
ctx.Books.Add(b4);
ctx.Books.Add(b5);
//将数据提交保存到数据库
await ctx.SaveChangesAsync();
2. 查询
using efCore;
//创建上下文对象,并使用using自动释放资源
using TestDbContext ctx = new TestDbContext();
//查询所有书
foreach(Book book in ctx.Books)
{Console.WriteLine($"Id={book.Id},Title={book.Title},Price={book.Price}");
}//查询价格高于80的书
IEnumerable<Book> books2 = ctx.Books.Where(b => b.Price > 80);
foreach (Book book in books2)
{Console.WriteLine($"Id={book.Id},Title={book.Title},Price={book.Price}");
}//查询单条数据,如果找不到则会报错
Book b1 = ctx.Books.Single(b=>b.Title=="零基础趣学C语言");
Console.WriteLine(b1.Title);//查询单条数据,找不到返回null
Book? b2 = ctx.Books.FirstOrDefault(b=>b.Id==9);
if(b2 == null)
{Console.WriteLine("没有ID为9的数据");
}
else
{Console.WriteLine(b2.Title);
}//按照价格排序
IEnumerable<Book> books = ctx.Books.OrderByDescending(b => b.Price);
foreach(Book book in books)
{Console.WriteLine($"Id={book.Id},Title={book.Title},Price={book.Price}");
}
3. 修改
using efCore;
using TestDbContext ctx = new TestDbContext();Book? b1 = ctx.Books.FirstOrDefault(b => b.Title == "数学之美");
if (b1 != null)
{b1.AuthorName = "张三";
}
await ctx.SaveChangesAsync();
4. 删除
using efCore;
using TestDbContext ctx = new TestDbContext();Book? b1 = ctx.Books.FirstOrDefault(b => b.Title == "数学之美");
if (b1 != null)
{ctx.Remove(b1);
}
await ctx.SaveChangesAsync();