1 EFCore是一个ORM框架
EFCore(EntityFramworkCore)是对底层ADO.NET重新封装的一个数据操作框架,因此ADO.NET支持的多种数据库都可以被EFCore支持。
EF Core 可用作对象关系映射程序 (O/RM),这可以实现以下两点:
- 使 .NET 开发人员能够使用 .NET 对象处理数据库。
- 避免SQL的编写。
- 开发更加高效
2 EFCore模型配置
EFCore的主要核心逻辑就是操作对象来处理数据库中的增删改查,因此.Net对象就需要对应着数据库中的实体表。因此要进行实体对象与数据库表的模型配置。
模型配置的方式有两种,基于特性与Fluent API
基于特性配置
/// <summary>
/// 使用Data_Annotation来进行模型映射
/// Table特性,指明表名
/// MaxLength,设定属性的最大长度,对应数据库即字段的最大长度
/// Required,属性不为空,意即数据库中该字段不可为空
/// </summary>
[Table("T_CAT")]
public class Cats
{
[Key]
[MaxLength(30)]
public string Id { get; set; }
[MaxLength(30)]
[Required]
public string Name { get; set; }
}
基于FluentAPI 配置
1 创建模型类
public class LabelConfig
{
public string ROW_ID { get; set; }
public string SYSTEM_NAME { get; set; }
public string SYSTEM_GROUP { get; set; }
public string LABEL_NAME { get; set; }
public string LABEL_LAN { get; set; }
public string LABEL_DESC { get; set; }
public string CREATE_EMP { get; set; }
public DateTime? CREATE_TIME { get; set; }
public string AGE1 { get; set; }
public string AGE2 { get; set; }
}
2 创建映射配置类
public class SignAgentConfig : IEntityTypeConfiguration<LabelConfig>
{
public void Configure(EntityTypeBuilder<LabelConfig> builder)
{
//TEntity与表C_SIGN_AGENT的映射关系
//未具体设置字段间的映射关系时,默认对象的属性和表的字段一一对应
builder.ToTable("REPLACE_LABEL_CONFIG");
//设置字段
builder.Property(i => i.ROW_ID).HasMaxLength(30).IsRequired();
//忽略Age2的映射
builder.Ignore(i=>i.AGE2);
//设置主键
builder.HasKey(i=>i.ROW_ID);
//设置列名映射
builder.Property(i => i.AGE1).HasColumnType("VARCHAR2(20)").HasColumnName("AGE");
//设置默认值
builder.Property(i => i.SYSTEM_GROUP).HasDefaultValue("defaltGroup");
//设置索引 IsUnique唯一索引
builder.HasIndex(i=>i.LABEL_NAME).IsUnique().HasName("Index1");
//设置复合索引
//IndexBuilder HasIndex([NotNullAttribute] Expression<Func<TEntity, object>> indexExpression)
//Expression<Func<TEntity, object>> indexExpression
builder.HasIndex(i => new
{
i.LABEL_NAME,
i.LABEL_LAN
//设置索引名称 HasName
}).HasName("Index2");
}
}
4 DbContext配置
/// <summary>
/// DbContext 类比与整个数据库中session连接,可在单次连接中操作DbSet<T>来操作数据库,如查找,
/// DbSet<TEntity> 类比与数据库中的单个表;当增加、移除表时,需要同时增加、移除DbSet<TEntity>属性
/// </summary>
public class MyDbContext:DbContext
{
public DbSet<LabelConfig> agents { get; set; }
public DbSet<Cats> cats { get; set; }
//配置数据库连接字符信息
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
string connection_str = "连接字符串";
//使用Oracle数据库
optionsBuilder.UseOracle(connection_str);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
//模型加载,加载当前Assembly程序集中继承了IEntityTypeConfiguration<T>的模型配置类
modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);
}
}
3 数据迁移Migration
根据实体类定义的变化生成的脚本,通过迁移动作同步到真实数据库中,简而言之,就是实体类属性的增加、移除动作,可通过Migration同步到数据中,相应产生的就是数据库字段的增加与移除动作。
在使用Migration功能之前,必须先要安装相应的nuget包(自行选择合适版本)。
Install-Package Microsoft.EntityFrameworkCore.Tools -Version 2.2.1
指令1: Add-Migration 【名称】
根据类模型类配置定义生成迁移脚本,通常后加一个迁移名称,标识当前类定义生成的最新迁移脚本。使用该指令后迁移脚本会在Migrations 文件夹中自动生成
使用Add-Migration update指令后,在Migrations生成了执行编号_Name,执行编号_Name.Designer两个执行脚本。
使用迁移脚本,可以对当前连接的数据库执行编号更高的迁移,这个操作叫做向上迁移(Up),也可以执行把数据库回退到旧的迁移,这个操作叫做向下迁移(Down)。除非有特殊需要,Migration文件下生成的迁移脚本不要轻易去删除。
指令2: Update-Databse
将类型定义变更到数据库中
5 EFCore与Linq语法的使用
class Program
{
/// <summary>
/// 使用DbContext实现增删改查;使用对象操作代替数据库中SQL的操作
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
using (MyDbContext context = new MyDbContext()) {
for (int i = 0; i < 10; i++)
{
LabelConfig c = new LabelConfig();
c.ROW_ID = i.ToString();
c.SYSTEM_NAME = "test";
c.SYSTEM_GROUP = "test";
c.LABEL_NAME = "Label" + i;
c.LABEL_DESC = "Label" + i;
c.LABEL_LAN = "ef-core-lan" + i;
c.CREATE_TIME = DateTime.Now;
//插入数据库
context.agents.Add(c);
}
//异步操作 保存数据表的变更 等价于Update - Database,一定要执行该方法
Task<int> res = context.SaveChangesAsync();
int qty = res.Result;
Console.OutputEncoding = Encoding.Unicode;
Console.WriteLine($"成功插入{qty}条数据");
//查询操作,可勇Linq语法,面向对象的操作来代替数据库的SQL操作
//因为DbContext中DbSet<TEntity>对象是一个继承了IEnumerable<T>的类,可以使用Linq语法来查询符合条件的对象
//ORM 查询出来的对象对应数据库中指定查询条件的行
var labels = context.agents.Where(item => item.SYSTEM_GROUP.Equals("test"));
foreach (LabelConfig label in labels) {
Console.WriteLine($"行标为{label.ROW_ID}的LabelName为{label.LABEL_NAME}");
}
//数据库update 操作 【update+delete操作】
//在EFCore中,update动作需要先查询处需要update、delete的数据,再进行update、delete操作,微软官方是为了保证数据库中数据的一致性
//这种变更操作,意味着批量删除、修改数据库中的数据时,效率低
var label_0 = context.agents.Where(i => i.LABEL_NAME.Equals("Label0")).First();
//属性的set操作,等价于 数据库中的update LABEL_LAN='zh-cn'
label_0.LABEL_LAN = "zh-cn";
label_0.CREATE_EMP = "F133222X";
label_0.CREATE_TIME = DateTime.Now;
res= context.SaveChangesAsync();
Console.WriteLine($"成功修改了{res.Result}条数据");
//刪除数据
var label_1 = context.agents.First(item => item.ROW_ID == "1");
context.agents.Remove(label_1);
res= context.SaveChangesAsync();
Console.WriteLine($"成功删除了{res.Result}条数据");
}
Console.ReadKey();
}
}