EF Core 二 、 入门 EF Core
入门EF Core
我们将开始真正的EF之旅了,这里使用SqlServer数据,然后DbFirst;
为嘛使用SqlServer,目前公司的整体业务全部在SqlSever,所以很多产品业务都是依托于这个,当然也在考虑做数据库切换,切换EF Core就是开始,为后续做好准备,目前SqlServer的linux集群部署太麻烦了,至少我是这样认为的,而且很多客户也都人格上排斥 .... 说多了都是泪 ....
然后就是DbFirst,公司是业务型公司,注重业务需求的设计,所以在需求开发之前,表结构的设计基本上都已经确定,基于现在的业务以及背景,可能DbFirst更加适合,当然Code First也不会丢掉的
一、安装 EF Core
新建类库,用来引用 Microsoft.EntityFrameworkCore.SqlServer

如果在项目中有类似的第三方程序集引用,建议放入统一的程序集,这样不用到处维护引用信息;而且有利于后期解耦,其他业务相关的都依赖统一接口就可以,这样具体的实现引用只是一个插件而已;
二、生成数据表结构
为了做测试,这里生成两张表,TestTable,以及TestTableDetail,用来模拟主从表的场景;一步步来啊
CREATE TABLE [dbo].[TestTable](
[Id] [INT] NOT NULL,
[Name] [NVARCHAR](200) NOT NULL,
PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[TestTableDetail](
[Id] [INT] NOT NULL,
[PID] [INT] NOT NULL,
[Name] [NVARCHAR](200) NOT NULL,
PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
三、建立实体对象
建立实体对象,用来与数据库的对象进行匹配
[Table("TestTable")]
public class TestTable
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
}
[Table("TestTableDetail")]
public class TestTableDetail
{
[Key]
public int Id { get; set; }
public int PID { get; set; }
public string Name { get; set; }
}
四、创建DbContext上下文
/// <summary>
/// 自定义 数据上下文
/// </summary>
public class MyDbContext : DbContext
{
public DbSet<TestTable> TestTables { get; set; }
public DbSet<TestTableDetail> TestTableDetails { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
//写入连接字符串
optionsBuilder.UseSqlServer("Data Source=.\\SQLSERVER2014;Initial Catalog=EfCore.Test;User ID=sa;Pwd=1");
}
}
DbContext是EF操作数据库的窗口,我们将为每个表来创建一个DbSet<>泛型类属性,用来操作具体的表对象;DbSet支持Linq操作;这里两个知识点:
1.如何配置连接字符串
如果是Asp.net Core程序,通常配置在Startup.cs中,需要导入 Microsoft.Extensions.Configuration 名命空间方可使用,按如下方式进行注册
public void ConfigureServices(IServiceCollection services) { services.AddDbContext<BloggingContext>(options => options.UseSqlServer(Configuration.GetConnectionString("BloggingDatabase")));
}
看下源码
EFCore.SqlServer
public static DbContextOptionsBuilder UseSqlServer(
[NotNull] this DbContextOptionsBuilder optionsBuilder,
[NotNull] string connectionString,
[CanBeNull] Action<SqlServerDbContextOptionsBuilder> sqlServerOptionsAction =
null)
{
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
Check.NotEmpty(connectionString, nameof(connectionString));
var extension =
(SqlServerOptionsExtension)GetOrCreateExtension(optionsBuilder).WithConnectionString(connectionString);
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
ConfigureWarnings(optionsBuilder);
sqlServerOptionsAction?.Invoke(new
SqlServerDbContextOptionsBuilder(optionsBuilder));
return optionsBuilder;
}
对DbContextOptionsBuilder进行扩展,提供了UseSqlServer方法,连接信息的提供都是通过 DbContextOptionsBuilder 来实现
针对WinForms以及WPF应用呢?我测试验证的就是控制台应用
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
//写入连接字符串
optionsBuilder.UseSqlServer("Data Source=.\\SQLSERVER2014;Initial Catalog=EfCore.Test;User ID=sa;Pwd=1");
}
这里我是固定了连接字符串,可以根据配置文件来写入了;可以看到也是对 DbContextOptionsBuilder 的 UseSqlSerer方法的调用;
查看源码:
DbContext
//定义虚方法OnConfiguring的位置
protected internal virtual void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
}
在InternalServiceProvider中进行了初始化调用,调用了OnConfiguring,从而进行了连接字符串的赋值;

2.是否需要为每个类都定义DbSet属性
如果业务系统过大,我们真的会定义一个DbContext,然后将所有Entity定义成DbSet<>?应该不会,这时我们可以通过反射来实现;
1.通过实现一个反射读取类,来动态读取实体类,也就是读取类具备 “Table”属性的目标类,或者自己集成一个父类用来识别实体类;
2.将读取到的实体类,动态加入到DbContext的实体模型中;
通过 重写 OnModelCreating 方法;微软官方文档地址:https://docs.microsoft.com/zh-cn/ef/core/modeling/
通过调用ModelBuilder.Entity方法直接贴代码:
/// <summary>
/// 自定义 数据上下文
/// </summary>
public class DynamicDbContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
//写入连接字符串
optionsBuilder.UseSqlServer("Data Source=.\\SQLSERVER2014;Initial Catalog=EfCore.Test;User ID=sa;Pwd=1");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var assembly = Assembly.GetExecutingAssembly();
foreach (Type type in assembly.ExportedTypes)
{
if (type.IsClass && type != typeof(EntityBase) && typeof(EntityBase).IsAssignableFrom((Type) type))
{
var method = modelBuilder.GetType().GetMethods().FirstOrDefault(x => x.Name == "Entity");
if (method != null)
{
method = method.MakeGenericMethod(type);
method.Invoke(modelBuilder, null);
}
}
}
base.OnModelCreating(modelBuilder);
}
}
整体思路还是两步走,先找到实体的实现类,然后通过调用DbContenxt的Entity方法;我们来看下DbContext源码;

最后通过Metadata.AddEntityType加入到实体模型,Metadata用来存储实体元数据;
还有两外一种实现方式,其实也就是衍生的方式了,因为查看源码得知最后实体被加入到了Medel中,那何不直接加入呢?

调用代码:
var myDbContext = new DynamicDbContext();
var list = myDbContext.Set<TestTable>().ToList();
Console.WriteLine($"TestTable Count: {list.Count}");
if (!list.Any()) return;
Console.WriteLine($"TestTable Detail ---------------- ");
foreach (var item in list)
{
Console.WriteLine($"ID : {item.Id} , Name : {item.Name}");
}
Console.WriteLine($"------------------------");
来看下执行效果吧....

这里的实现让我想到了ABP数据仓储的实现,ABP为每个实体创建一个仓储对象,不需要手动一个个创建,可以查看我的ABP系列 => ABP 数据访问 - IRepository 仓储 ,可以参考ABP仓储管理的思想;大家也可以去看下
五、数据访问
好了,回到最初的实现思路上,前面的准备工作都做的差不多了,该正式跑一把数据了....
public static void Query_查询数据_全量查询()
{
var myDbContext = new MyDbContext();
var list = myDbContext.TestTables.ToList();
Console.WriteLine($"TestTable Count: {list.Count}");
if (!list.Any()) return;
Console.WriteLine($"TestTable Detail ---------------- ");
foreach (var item in list)
{
Console.WriteLine($"ID : {item.Id} , Name : {item.Name}");
}
Console.WriteLine($"------------------------");
}
通过控制台应用,执行上述方法,即可查询到TestTable中的数据

到此我们基本就开始使用EF Core,实现了数据访问;后续将开始对EF的其他使用持续进行分析,以及一些高阶应用;
文章后面附上EFCore的源码地址,一起看源码,一起学习 https://github.com/dotnet/efcore
帮助博客园推广下:https://www.cnblogs.com/cmt/p/14003277.html
EF Core 二 、 入门 EF Core的更多相关文章
- K8S+GitLab-自动化分布式部署ASP.NET Core(二) ASP.NET Core DevOps
一.介绍 前一篇,写的K8S部署环境的文章,简单的介绍下DevOps(Development和Operations的组合词),高效交付, 自动化流程,来减少软件开发人员和运维人员的沟通.Martin ...
- EF Core 快速上手——EF Core 入门
EF Core 快速上手--EF Core 介绍 本章导航 从本书你能学到什么 对EF6.x 程序员的一些话 EF Core 概述 1.3.1 ORM框架的缺点 第一个EF Core应用 本文是对 ...
- asp.net core系列 30 EF管理数据库架构--必备知识 迁移
一.管理数据库架构概述 EF Core 提供两种主要方法来保持 EF Core 模型和数据库架构同步.一是以 EF Core 模型为基准,二是以数据库为基准. (1)如果希望以 EF Core 模型为 ...
- EF Core 快速上手——EF Core的三种主要关系类型
系列文章 EF Core 快速上手--EF Core 入门 本节导航 三种数据库关系类型建模 Migration方式创建和习修改数据库 定义和创建应用DbContext 将复杂查询拆分为子查询 本 ...
- asp.net core系列 31 EF管理数据库架构--必备知识 反向工程
一. 反向工程 反向工程是基于数据库架构,生成的实体类和DbContext类代码的过程,对于Visual Studio开发,建议使用PMC.对于其他开发环境,请选择.NET Core CLI工具( ...
- asp.net core 系列 20 EF基于数据模型创建数据库
一.概述 本章使用 Entity Framework Core 构建执行基本数据访问的 ASP.NET Core MVC 应用程序.使用迁移(migrations)基于数据模型创建数据库,是一种cod ...
- EF 6.x、EF Core实现dynamic动态查询和EF Core实现多个上下文实例池你了解多少?
前言 很长一段时间没有写博客了,今天补上一篇吧,偶尔发现不太愿意写博客了,太耗费时间,不过还是在坚持当中,毕竟或许写出来的东西能帮到一些童鞋吧,接下来我们直奔主题.无论是在在EF 6.x还是EF Co ...
- 讨论过后而引发对EF 6.x和EF Core查询缓存的思考
前言 最近将RabbitMQ正式封装引入到.NET Core 2.0项目当中,之前从未接触过是个高大上的东东跟着老大学习中,其中收获不少,本打算再看看RabbitMQ有时间写写,回来后和何镇汐大哥探讨 ...
- Asp.Net Core WebAPI入门整理(二)简单示例
一.Core WebAPI中的序列化 使用的是Newtonsoft.Json,自定义全局配置处理: // This method gets called by the runtime. Use thi ...
随机推荐
- 【源码项目+解析】C语言/C++开发,打造一个小项目扫雷小游戏!
一直说写个几百行的小项目,于是我写了一个控制台的扫雷,没有想到精简完了代码才200行左右,不过考虑到这是我精简过后的,浓缩才是精华嘛,我就发出来大家一起学习啦,看到程序跑起来能玩,感觉还是蛮有成就感的 ...
- 数据库SQL Server 2016“功能选择”详细说明及精简安装选择
前言 在平时大家安装数据库的时候,一般默认功能选择都会选择全选.但是前两天公司同事问我:"那么多功能为什么都能用到嘛?"顿时,我思考了一下确实没有详细了解每个功能的详细作用,于是花 ...
- JVM系列【6】GC与调优5-日志分析
JVM系列笔记目录 虚拟机的基础概念 class文件结构 class文件加载过程 jvm内存模型 JVM常用指令 GC与调优 主要内容 分析PS.CMS.G1的回收日志,目标使大概能读懂GC日志. 测 ...
- kafka-消费者测试
1. 在窗口1创建一个producer,topic为test,broker-list为zookeeper集群ip+端口 /usr/local/kafka/bin/kafka-console-pro ...
- zookeeper-(单机,伪集群)
安装zookeeper(单机,伪集群): 1.下载 登陆zookeeper官网下载 https://zookeeper.apache.org/ 或者 https://mirror.bit.e ...
- Ubuntu安装zookeeper问题
在Ubuntu系统安装zookeeper后,启动报错: root@host8:/usr/solrcould/service1/zookeeper-3.5.0-alpha# sh bin/zkServe ...
- Callable接口
Callable与Runnable的不同区别在于: 1.Callable有返回值 Runnable没有返回值 2.Callable需要实现的方法是call方法 Runnable需要实现的方 ...
- RxJava用法
首先导入依赖: implementation 'io.reactivex.rxjava2:rxjava:2.2.9'implementation 'io.reactivex.rxjava2:rxand ...
- [C#.NET 拾遗补漏]10:理解 volatile 关键字
要理解 C# 中的 volatile 关键字,就要先知道编译器背后的一个基本优化原理.比如对于下面这段代码: public class Example { public int x; public v ...
- 详解MapReduce(Spark和MapReduce对比铺垫篇)
本来笔者是不打算写MapReduce的,但是考虑到目前很多公司还都在用这个计算引擎,以及后续要讲的Hive原生支持的计算引擎也是MapReduce,并且为Spark和MapReduce的对比做铺垫,笔 ...