.NET Core EF Core
.NET Core EF Core
一.什么是ORM
1.ORM:Object Relation Mapping. 让开发者用对象操作的形式操作关系数据库.
比如插入:
User user = new User(){Name="admin",Password="123"};
orm.Save(User);
比如查询:
Book b = orm.Book.Single(b=>b.Id==3||b.Name.Contains(".NET"));
string bookName = b.Name;
string aName = a.Author.Name;
2.有哪些ORM:EF core,Dapper,SQLSugar,FreeSql
二.EF Core与其他ORM比较
1.Entity Framework Core(EF Core)是微软的ORM框架
优点:功能强大,官方支持,生产效率高,力求屏蔽底层数据库差异;
缺点:复杂,上手门槛高,不熟悉EFCore的话可能会进坑
2.Dapper
优点:简单,N分钟即可上手,行为可预期性强
缺点:生产效率低,需要处理
3.EF Core是模型驱动(Model-Driven)的开发思想,Dapper是数据库驱动(DataBase-Driven)的开发思想的,没有优劣,只有比较
4.性能:Dapper等 不等于 性能高;EF Core 不等于 性能差
5.EF Core是官方推荐,推进的框架,尽量屏蔽底层数据库差异,.NET开发者必须熟悉,根据的项目情况再决定用哪个
三.EF Core用什么数据库
1.EF Core是对于底层ADO.NET Core的封装,因此ADO.NET Core支持的数据库不一定被EF Core支持.
2.EF Core支持所有主流的数据库,包括MS SQL Server,Oracle,MySQL,PostgreSQL,SQLite等.可以自己实现Provider支持其他数据库.
3.对于SQLServer支持最完美,MySQL,PostgreSQL也不错
四.开发环境搭建
1.经典步骤:
建实体类;
建DbContext;
生成数据库;
编写调用EF Core的业务代码
2.Book.cs
public class Book
{
public long Id { get; set; }//主键
public string Title { get; set; }//标题
public DateTime PubTime { get; set; }//发布日期
public double Price { get; set; } //单价
}
3.Install-Package Microsoft.EntityFrameworkCore.SqlServer
4.创建实现了IEntityTypeConfiguration接口的实体配置类,配置实体类的数据表的对应关系 BookConfig.cs
class BookConfig : IEntityTypeConfiguration<Book>
{
public void Configure(EntityTypeBuilder<Book> builder)
{
builder.ToTable("T_Books");
}
}
5.创建继承自DbContext的类
class MyDbContext : DbContext
{
public DbSet<Book> Books { get; set; }
public DbSet<Person> Persons { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
optionsBuilder.UseSqlServer("");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
//从当前程序集加载所有的IEntityTypeConfiguration
modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);
}
2.Migration
概念:Migration数据路迁移
面向对象的ORM开发中,数据库不是程序员手动创建的,而是由Migration工具生成的.关系数据库只是盛放模型数据的一个媒介而已,理想状态下,程序员不用关系数据库的操作.
根据对象的定义变化,自动更新数据库中的表以及表结构,叫做Migration(迁移).
迁移可以分为多步(项目进化),也可以回滚.
1.安装Migration
Install-Package Microsoft.EntityFrameworkCore.Tools
再在"程序包管理控制台"中执行如下命令
Add-Migration InitialCreate
会自动在项目的Migration文件夹中中生成操作数据库的C#代码.讲解一下生成代码的作用
InitialCreate是什么?
2.代码需要执行后才会应用对数据库的操作,"程序包管理器控制台"中执行
Update-database
3.查看一下数据库,表就建好了
3.修改表结构
1.项目开发中,根据需要,可能会在已有实体中修改,新增,删除表列等
2.想要限制Title的最大长度为50,Title字段设置为"不可为空",并且想增加一个不可为空且最大长度为20的AuthorName(作者名字)属性
首先在Book实体类中增加一个AuthorName属性
public class Book
{
public long Id { get; set; }//主键
public string Title { get; set; }//标题
public DateTime PubTime { get; set; }//发布日期
public double Price { get; set; } //单价
public string AuthorName { get; set; }//作者名字
}
3.修改BookEntityConfig
public void Configure(EntityTypeBuilder<Book> builder)
{
builder.ToTable("T_Books");
builder.Property(b => b.Title).HasMaxLength(50).IsRequired();
builder.Property(b => b.AuthorName).HasMaxLength(20).IsRequired();
}
4.插入数据
1.只要操作Books属性,就可以向数据库中增加数据,但是通过C#代码修改Books中的数据只是修改了内存中的数据.
对Books修改后,现需要调用DbContext的异步方法==SaveChangeAsync()==把修改保存到数据库.也有同步的保存方法SaveChanges(),但是用EF Core都推荐用异步方法.
2.EF Core默认会跟踪(Track)实体类对象以及DbSet的改变.
3.演示数据插入
static async Task Main(string[] args)
{
//ctx=逻辑上的数据库
using (MyDbContext ctx = new MyDbContext())
{
Dog d = new Dog();
d.Name = "Trump";
ctx.Dogs.Add(d);//把d对象加入Dogs这个逻辑上的表里面
await ctx.SaveChangesAsync();
}
}
5.查询数据
1.DbSet实现了IEnumerable接口,因此可以对DbSet实施Linq操作来进行数据查询,EF Core会把Linq操作转换为SQL语句,面向对象,而不是面向数据库(SQL).
IQueryable books = ctx.Books.Where(b => b.Price > 80);
2.可以使用OrderBy操作进行数据的排序
var booksPrice = ctx.Books.OrderBy(b => b.Price).Where(b=>b.Price<10);
foreach (var book in booksPrice)
{
Console.WriteLine(book.Title +"======"+book.Price);
}
6.修改,删除
1.要对数据进行修改,首先需要把修改的数据查询出来,然后再对查询出来的对象进行修改,然后再执行SaveChangesAsync()保存修改
var b = ctx.Books.Single(b => b.Title == “算法”);
b.AuthorName = “xiaomimi”;
2.删除也是先把要修改的数据查询出来,然后再调用DbSet或者DbContext的Remove方法把对象删除,然后再执行
SaveChangeAsync()保存修改.
var d = ctx.Dogs.Where(b => b.Id > 3);
ctx.Dogs.RemoveRange(d);await ctx.SaveChangesAsync();
7.批量修改,删除
1.目前批量修改,删除多条数据的方法
局限性:性能低:查出来,再一条条Update,Delete,而不能执行Update…where;delete…Where;
2.官方目前还没有支持高效的批量Update,Delete,有在后续版本中增加
8.约定配置
主要规则:
1.表名采用DbContext中的对应的DbSet的属性名
2.数据表列的名字采用实体类属性的名字,列的数据类型采用和实体类属性类型最兼容的类型
3.数据列表的可空性取决于对应实体类属性的可空性.
4.名字为Id的属性为主键,如果主键为short,int或者long类型,则默认采用自增字段,如果主键为Guid类型,则默认采用默认的Guid生成机制生成主键值
1.两种配置方式
1.Data Annotation
把配置以特性(Annotation)的形式标注在实体类中
[Table("T_Books")]
public class Book
{
}
优点:简单
缺点:耦合
[Table("T_Cats")]
class Cats
{
public long Id { get; set; }
[Required]
[MaxLength(22)]
public string Name { get; set; }
}
2.Fluent API
builder.ToTable("T_Books");
把配置写到单独的配置类中
缺点:复杂
优点:解耦
1.视图与实体类的映射:
modelBuilder.Entity().ToView(“blogsView”);
2.排除属性映射
moderBuilder.Entity().Ignore(b=>b.Name2);
3.配置列名:
modelBuilder.Entity.Property(b=>b.BlogId).HasColumnName(“blog_id”);
4.配置列数据类型
builder.Property(e=>e.Title).HasColumnType(“varchar(200)”)
5.配置主键
默认吧名字为Id或者"实体类型+Id"的属性作为主键,可以用HasKey()来配置其他属性作为主键
modelBuilder.Entity().HasKey(c=>c.Number);
支持符合主键,但是不建议使用
6.生成列的值
modelBuilder.Entity().Property(b=>b.Number).ValueGeneratedOnAdd();
7.可以用HasDefaultValue()为属性设定的默认值
modelBuilder.Entity().Property(b=>b.Age).HasDefaultValue(6);
8.索引
modelBuilder.Entity().HasIndex(b=> b.Url);
复合索引
modelBuilder.Entity().HasIndex(p=>new{p.FirstName,p.LastName});
唯一索引:IsUnique();
聚集索引:IsClustered()
9… 用EF Core太多高级特性的时候谨慎,尽量不要和业务逻辑混合在一起,以免"不能自拔"
比如Ignore,Shadow,Table Splitting等…
3.大部分功能重叠,可以混用,但是不建议混用
2.选择
1.Data Annotation,Fluent API大部分功能重叠,可以混用,但是不建议混用
2.有人建议混用,即用了Data Annotation的简单,有用到Fluent API的强大,而且实体类上标注的[MaxLength(50)],[Required]等标注可以被ASP.NET Core中的验证框架等复用
9.自增主键
1.EF Core支持多种主键生成策略:自动正常,Guid;Hi/Lo算法等
2.自动增长.
优点:简单;
缺点:数据库迁移以及分布式系统中比较麻烦;并发性能差.long,int等类型主键,默认是自增.因为是数据库生成的值,所以SaveChanges后会自动把主键的值更新到Id属性
3.自增字段的代码中不能为Id赋值,必须保持默认值0,否则运行的时候就会报错.
10.Guid主键
1.Guid算法(或UUID算法)生成一个全局唯一的Id.适合于分布式系统,在进行多数据库数据合并的时候很简单.
优点:简单 高并发 全局唯一
缺点:磁盘空间占用很大
2.Guid值不连续,使用Guid类型做主键的时候,不能把主键设置为聚集索引,因为聚集索引时按照顺序保存主键的,因此用Guid做主键性能较差.
比如MySQL的InnoDb引擎中主键是强制使用聚集索引的.有的数据库支持部分连续Guid,比如SQL Server中的NewSequentialId(),但也不能解决问题.在SQL Server等中,不要把Guid主键设置为聚集索引;在MySQL中,插入频繁的表不要用Guid做主键
3.演示Guid用法
既可以让EF Core给赋值,也可以手动赋值
11.其他主键方案
1.混合自增的Guid(非复合主键).用自增列做物理的主键,而用Guid列做逻辑上的主键.把自增列设置为表的主键,而在业务上查询数据时候把Guid当主键用.在和其他表关联以及和外部系统通讯的时候(比如前端显示数据的标识的时候)都是使用Guid列.不进保证了性能,而且利用了Guid的有点,而且减轻了自增主键导致主键值可被预测带来的安全性问题
2.Hi/Lo算法:EF Core支持Hi/Lo算法来优化自增列,主键值由两部分组成:高位(Hi)和低位(Lo),高位由数据库生成,两个高位之间间隔若干个值,由程序在本地生成低位,低位的值在本地自增生成.不同进程或者集中不同服务器获取的Hi值不会重复,而本地进程计算的Lo则可以保证在本地高效率的生成主键值,但是HiLo算法不是EF Core的标准
上一篇: 力扣二分查找
下一篇: 力扣java 二分查找
推荐阅读
-
ASP.NET Core 3.X IConfiguration取值
-
ASP.NET Core SignalR.NET 客户端
-
[ASP.NET Core 3.0学习笔记] - SignalR
-
ASP.NET Core 聊天室实现(SignalR)
-
.net Core 中signalR的实现
-
Asp.Net Core 2.1 中 利用SignalR 服务端主动推送数据
-
Asp.Net Core使用SignalR进行服务间调用
-
jenkins 读取json文件_干货:.net core实现读取appsettings.json配置文件(建议收藏)...
-
asp.net core identity 配置cookie
-
.Net Core之SignalR