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 ...
随机推荐
- gin教程
Golang Gin 实战(十)| XML渲染 Golang Gin 实战(九)| JSONP跨域和劫持 Golang Gin 实战(八)| JSON渲染输出 Golang Gin 实战(七)| 分组 ...
- nginx给consul集群配置负载均衡
upstream consul { server 127.0.0.1:8501; server 127.0.0.1:8502; server 127.0.0.1:8503; } server { li ...
- SpringApplication.run(xxx.class, args)背后的东东——整体脉络
从spring到springmvc,再到springboot.springcloud,应用程序api开发调用方面都已经非常熟悉,但对spring背后的扩展机制:为何一个简单的main方法可以实现这么强 ...
- C# stopwatch的简单使用(计算程序执行时间)
首先添加引用 using System.Diagnostics;//stopwatch的引用 //声明变量 Stopwatch a=new Stopwatch();//PS:这里一定要new(实例化) ...
- Linux 环境编程:dirfd参数 有关解析
背景 在Unix环境编程中,系统提供了很多以at结尾的函数,如openat.fstatat等,而这类函数通常有一个特点,就是形参列表中多了int dirfd 例如: int open(const ch ...
- 常用命令--windows
查看端口号是否占用并杀进程 1 netstat -ano | findstr " " 2 tasklist | findstr " " 3 taskkill / ...
- pycharm pro2020版专业版永久激活
pycharm2020版本专业版永久激活[亲测有效] pycharm2020.1版安装包与破解工具下载 可私信我获取资源. 公众号,轻松学编程 教程 1.先下载安装包和破解补丁压缩包,然后点击pych ...
- layui table中固定表头,弹框缩放之后,表头对不齐问题
新手一枚 直接上解决方案 在layui弹出成功后再渲染表格数据 具体操作就是在layer弹层完成之后的回调中渲染表格数据 layer.open({ type: 1, content: $(&quo ...
- 深入web workers (上)
前段时间,为了优化某个有点复杂的功能,我采用了shared workers + indexDB,构建了一个高性能的多页面共享的服务.由于是第一次真正意义上的运用workers,比以前单纯的学习有更多体 ...
- 1、Web应用
一 Web应用的组成 接下来我们学习的目的是为了开发一个Web应用程序,而Web应用程序是基于B/S架构的,其中B指的是浏览器,负责向S端发送请求信息,而S端会根据接收到的请求信息返回相应的数据给浏览 ...