搭建EF Core开发环境
EF Core是对于底层ADO.NET Core封装
1.建立实体类
建立Book.cs类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EFCore_demo
{
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; }//作者名字
}
}
建立Person.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EFCore_demo
{
public class Person
{
public long Id { get; set; }//主键
public string Name { get; set; }
public int Age { get; set; }
}
}
PM> Install-Package Microsoft.EntityFrameworkCore.SqlServer
2.建立配置类Config
创建实现了IEntityTypeConfiguration接口的实体配置类,配置实体类和数据表的对应关系(这里约定大于配置)
创建BookConfig.cs
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EFCore_demo
{
class BookConfig : IEntityTypeConfiguration
{
public void Configure(EntityTypeBuilder builder)
{
builder.ToTable("T_Books");
}
}
}
创建PersonConfig
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EFCore_demo
{
class PersonConfig : IEntityTypeConfiguration
{
public void Configure(EntityTypeBuilder builder)
{
builder.ToTable("T_Persons");
}
}
}
3.建立DbContext
创建继承DbContext的类
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EFCore_demo
{
class MyDbContext : DbContext
{
public DbSet Books { get; set; }
public DbSet Persons { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
string connStr = "Server=SHA-CLPS-D36;Database=Csharp_demo;Trusted_Connection=True;Encrypt=True;TrustServerCertificate=True";
//string connStr = "Data Source = SHA-CLPS-D36; Initial Catelog= Csharp_demo; Integrate Security= true";
optionsBuilder.UseSqlServer(connStr);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);
}
}
}
Onconfiguration说明连接哪一个数据库
OnModeCreating从哪里加载IentityConfiguration
这里我遇到一个报错问题(已解决)
Error Number:-2146893019,State:0,Class:20
A connection was successfully established with the server, but then an error occurred during the login process. (provider: SSL Provider, error: 0 - The certificate chain was issued by an authority that is not trusted.)
解决方法:
在登录时,更改选项的连接属性,解决方案、信任服务器证书选项都选择或者都不选择,不能只选一个
连接字符串里的设置是:Encrypt=True;TrustServerCertificate=True
4.生成数据库
Migration(迁移)工具生成数据库,在面对对象的ORM开发中。根据对象的定义变化,自动更新数据库中的表以及表结构的操作.
为了使用生成数据库工具,Nuget安装Microsoft.EntityworkCore.Tools先
Install-Package Microsoft.EntityFrameworkCore.Tools
然后执行Add-Migration命令
Add-Migration InitialCreate
代码需要执行后才会应用对数据库的操作
Update-database
每更新一次,都是一个新的Migration文件,所以每次都需要给他一个名字-合法变量名,有意义
Add-Migration ***
连接成功,并成功创建表
修改已创建好的表结构(实体中修改,新增,删除表,列等)
(1)新增一个实体
为了这个实体能和数据库产生关系,一定要在MyDbContext里面声明
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EFCore_demo
{
public class Dog
{
public long Id { get; set; }//主键
public string Name { get; set; }
}
}
(2).新增属性
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EFCore_demo
{
public class Person
{
public long Id { get; set; }//主键
public string Name { get; set; }
public int Age { get; set; }
public string BirthPlace { get; set; }//新增出生地
public double? Salary { get; set; }//加个?表示可空的salary
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EFCore_demo
{
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)修改列的属性
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EFCore_demo
{
class BookConfig : IEntityTypeConfiguration
{
public void Configure(EntityTypeBuilder builder)
{
builder.ToTable("T_Books");
builder.Property(b=>b.Title).IsRequired().HasMaxLength(50);
builder.Property(b => b.AuthorName).IsRequired().HasMaxLength(50);
}
}
}
所有修改结束记得重新Add-Migration ***,再Update-database
5.EF Core数据的增删改查
(1)插入数据
首先new一个DbContext对象,避免资源泄漏,需要using一下。
调用Add()方法,然后SaveChanges()才真正加入。
ctx有异步方法,我们需要养成用异步方法的好习惯,后面我们都是用异步方法。
using System;
namespace EFCore_demo // Note: actual namespace depends on the project name.
{
internal class Program
{
static async Task Main(string[] args)
{
//crx=逻辑上的数据库
using(MyDbContext ctx=new MyDbContext())
{
Dog d=new Dog();
d.Name = "wangcai";
ctx.Add(d);//把d对象加入Dogs这个逻辑上的表里面
//ctx.SvaceChanges();//Update-Database
Book b= new Book();
b.AuthorName = "rachel";
b.Price = 18;
b.PubTime=DateTime.Now;
b.Title= "C language";
ctx.Add(b);
await ctx.SaveChangesAsync();
}
}
}
}
(2)查询数据(请事先将表中插入一些数据以便查询)
DbSet实现了IEnumberable
using System;
using System.Linq;
namespace EFCore_demo // Note: actual namespace depends on the project name.
{
public class Program
{
static async Task Main(string[] args)
{
//crx=逻辑上的数据库
using (MyDbContext ctx = new MyDbContext())
{
//select * from xxx from price>80
//var books= ctx.Books.Where(b=>b.Price>10);
var books = ctx.Books.Where(b => b.Price > 0);
foreach (var b in books)
{
Console.WriteLine(b.Title);
}
//查询不需要SaveChangeAsync();
//await ctx.SaveChangesAsync();
}
}
}
}
(3) 删除数据
删除也是先把要修改的数据查询出来,然后再调用Dbset或者DbContext的Remove方法把对象删除,然后再执行SaveChangeAsync()保存修改。
using System;
using System.Linq;
namespace EFCore_demo // Note: actual namespace depends on the project name.
{
public class Program
{
static async Task Main(string[] args)
{
//crx=逻辑上的数据库
using (MyDbContext ctx = new MyDbContext())
{
var b = ctx.Books.Single(b => b.Id == 2);
b.Title = "java is best language";
await ctx.SaveChangesAsync();
}
}
}
}
(4)更新数据
要对数据进行修改,首先需要把要修改的数据查询出来,然后再对查询出来的对象进行修改然后再执行SaveChangeAsync()保存修改。
using System;
using System.Linq;
namespace EFCore_demo // Note: actual namespace depends on the project name.
{
public class Program
{
static async Task Main(string[] args)
{
//crx=逻辑上的数据库
using (MyDbContext ctx = new MyDbContext())
{
//select * from xxx from price>80
//var books= ctx.Books.Where(b=>b.Price>10);
var b = ctx.Books.Single(b => b.Title == "SQL");
ctx.Remove(b);//也可以写成ctx.Books.Remove(b);
await ctx.SaveChangesAsync();
}
}
}
}
6.实体的配置
约定配置:
主要规则:
两种配置方式
(1)DataAnnotation
把配置以特性(Annotation)的形式标注在实体类中。
[table("T_Books")]
public class Book
{
}
优点:简单。缺点:耦合
(2)Fluent API
builder.ToTable("T_Books");
把配置写到单独的配置类中。
缺点:复杂。优点:解耦
7.编写调用EFCore的业务代码