欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

.NET Core EF Core

程序员文章站 2022-03-09 13:55:13
...

.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的标准

相关标签: .NET CORE c#