.Net Core 2.0生态(4):Entity Framework Core 2.0 特性介绍和使用指南
前言
这是.Net Core 2.0生态生态介绍的最后一篇,EF一直是我喜欢的一个ORM框架,随着版本升级EF也发展到EF6.x,Entity Framework Core是一个支持跨平台的全新版本,可以用三个词来概况EF Core的特点:轻量级、可扩展、跨平台。跨平台的特性是EF6.x无法替代的优势,也许会成为你在项目中技术选型的原因之一。
对于.NET Core 2.0的发布介绍,围绕2.0的架构体系,本系列相关文章:
- .Net Core 2.0 生态(1).NET Standard 2.0 特性介绍和使用指南(已发布)
- .Net Core 2.0 生态(2).NET Core 2.0 特性介绍和使用指南(已发布)
- .Net Core 2.0 生态(3)ASP.NET Core 2.0 特性介绍和使用指南(已发布)
- .Net Core 2.0 生态(4)Entity Framework Core 2.0 特性介绍和使用指南(已发布)
获取和使用
在命令行工具安装NuGet包,比如:安装SQL Server EF Core提供程序,并指定版本为2.0.0
。
$ dotnet add package Microsoft.EntityFrameworkCore.SqlServer -V 2.0.0
在VS2017中使用包管理器控制台安装
PM> Install-Package Microsoft.EntityFrameworkCore.SqlServer -Version 2.0.0
在ASP.NET Core 2.0默认项目包含支持EF Core 2.0的SQL Server, SQLite, 和 in-memory数据库提供程序,创建项目无需额外添加。
查看在不同平台上使用EF Core指南,查看更多安装和升级细节,进入帮助文档。
新特性
以下是最显著的新特性:
使用.NET Standard 2.0目标框架:这使得EF Core 2.0可支持多种.NET平台实现和应用程序类型,查看平台支持列表。
LINQ解析改进:EF Core 2.0中的查询更加高效,适应多种场景。举个例子,增加了翻译成SQL语句模式的数量限制,避免了在以前版本中因为客户端计算导致多重查询的问题。(优化了客户端计算性能)
Like查询支持:LINQ查询可以使用
EF.Functions.Like()
,最终解析为SQL中的like
语句,在必要的时候会进行内存计算,举个例子,下面的查询:var customers =
from c in context.Customers
where EF.Functions.Like(c.Name, "a%");
select c;
解析成SQL语句:
SELECT [c].[Id], [c].[Name]
FROM [Customers] AS [c]
WHERE [c].[Name] LIKE N'a%';
和SQL中like语句一样使用通配符。
实体包含关系和表拆分:可以通过属性关联建立实体之间的包含关系,这个特性和EF6中的复合类型类似,只需要定义一个导航属性。实体包含关系定义与表拆分结合使用,可以将两个实体自动映射为单张表,参看下面的示例:
public class Customer
{
public int Id { get; set; }
public string Name {get; set;}
public PhysicalAddress Address { get; set; }
} public class PhysicalAddress
{
public string StreetAddress { get; set; }
public Location Location { get; set; }
} ... modelBuilder.Entity<Customer>()
.OwnsOne(c => c.Address);
全局查询过滤器:在DbContext中为实体定义查询过滤器,下面代码在
OnModelCreating
方法中定义:modelBuilder.Entity<Post>()
.HasQueryFilter(p => !p.IsDeleted);
下面的查询只会返回未被标记为删除的结果:
var blog = context.Blogs
.Include(b => b.Posts)
.FirstOrDefault(b => b.Id == id);
这个特性在特殊的业务场景下将有大用处,比如多租户中数据过滤实现。
DbContext Pooling(池):这项特性能够显著提升Asp.net Core应用程序的性能,通过在服务注册
DbContext
类型时启用,使用预先创建的实例池,避免为每个请求创建新实例:services.AddDbContextPool<BloggingContext>(
options => options.UseSqlServer(connectionString));
这是一个最佳实践,推荐使用!
SQL方法支持字符串插值:下面的SQL语句使用了C#中字符串插值语法,简化参数化查询:
var city = "Redmond"; using (var context = CreateContext())
{
context.Customers.FromSql($@"
SELECT *
FROM Customers
WHERE City = {city}");
}
以上代码转换为SQL语句会创建一个名为
@p0
的参数,值为Redmond
,生成如下SQL语句:SELECT *
FROM Customers
WHERE City = @p0
更多特性:如:显式编译查询、自包含实体配置、数据库标准函数映射。还修复了许多Bug。详细内容参考:新功能
项目升级和核心API变化
- 将项目.NET平台设置为支持.NET Standard 2.0的平台
- 使用支持2.0的数据库提供程序
- 更新EF Core引用包(包括运行时和工具)到2.0
- 必要的时候对代码进行修改,具体参看核心变化
在2.0版本中,部分API和操作有较大改进,有部分改进需要修改现有程序代码,对于大多数应用程序来说,影响不大,大多数情况下,只需要重新编译和最少的修改来替换过时的API。
获取应用程序服务新方式
注:EF Core在设计时的操作比如生成数据迁移代码,更新数据库,需要访问应用程序服务。设计时工具和应用程序存在调用关系。
推荐将ASP.NET Core Web应用程序更新到2.0,在ASP.NET Core 2.0在启动类之外初始化配置。在之前的版本EF Core尝试执行Startup.ConfigureServices
,直接访问应用程序的服务提供者,使用EF Core的应用程序通常从配置文件中访问连接字符串,所以单靠Startup
已经不能满足获取连接字符串的需要。
更新ASP.NET Core 1.x到2.0,当使用了EF Core工具,会收到如下错误提示:
No parameterless constructor was found on 'ApplicationContext'. Either add a parameterless constructor to 'ApplicationContext' or add an implementation of 'IDesignTimeDbContextFactory' in the same assembly as 'ApplicationContext'
在ASP.NET Core 2.0默认模板中新增设计时支持,静态方法Program.BuildWebHost
允许EF Core在设计时访问应用程序服务提供者,如果升级ASP.NET Core 1.x应用程序,同时升级Program
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
namespace AspNetCoreDotNetCore2._0App
{
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
}
注:如果没有ASP.NET Core 2.0应用程序没有更改Program启动方式,依然可以使用实现
IDesignTimeDbContextFactory<ApplicationContext>
接口方式提供EF Core 2.0设计时支持,不推荐这么做。
IDbContextFactory改名
为了支持不同的应用模式,在设计时提供对DbContext
更多自定义控制,在以前的版本提供接口IDbContextFactory<TContext>
,EF Core工具在设计时,会发现应用程序中该接口的实现并使用它来创建DbContext
对象。
这个接口因为具有通用性的名称,容易误导开发者使用来处理需要重新创建DbContext
的开发场景,当在设计时EF Core工具使用它时因为没有考虑到设计时的特殊环境可以导致Update-Database
或dotnet ef database update
命令执行失败。
基于以上的原因,为了更精准的表达该接口的作用,我们将其改名为IDesignTimeDbContextFactory<TContext>
,在2.0中IDbContextFactory<TContext>
仍然存在,但是已经标记为过时了。
DbContextFactoryOptions移除
因为ASP.NET 2.0的升级,我们发现在接口IDesignTimeDbContextFactory<TContext>
不在需要DbContextFactoryOptions
。
下面是你应该使用的替代方案。
- DbContextFactoryOptions.ApplicationBasePath 使用AppContext.BaseDirectory代替
- DbContextFactoryOptions.ContentRootPath 使用Directory.GetCurrentDirectory()代替
- DbContextFactoryOptions.EnvironmentName 使用Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")代替
EF Core 2.0需要2.0数据库提供程序
对于EF Core 2.0,我们已经对数据库提供程序的工作进行了许多简化和改进。1.0.x和1.1.x提供程序已经不能在EF Core 2.0下工作。
由EF团队开发的SQL Server和SQLite数据库提供程序,2.0版本将在2.0版本中提供。其他数据库提供程序也已经升级到2.0版本:
日志记录和诊断事件更改
注意:这些更改不会影响大多数的应用程序代码。
发送给ILogger的消息的事件ID在2.0中发生了变化。现在在EF Core中事件ID是全局唯一的。这些消息现在也遵循了结构化日志的标准模式,例如,MVC。
Logger类别也发生了变化,类别可通过DbLoggerCategory
访问。
DiagnosticSource事件现在使用与对应ILogger消息相同的时间ID名称,事件ID、有效负载类型和类别进行了统一。
ID从Microsoft.EntityFrameworkCore.Infraestructure
命名空间移到Microsoft.EntityFrameworkCore.Diagnostics
。
EF Core元数据关系API变化
EF Core 2.0为不同的提供程序创建一个不同的IModel
,这通常对应用程序是透明的,从而简化了底层元数据API,使得任何对公共关系的元数据都可以通过调用来实现,对比如下代码,在1.1.x中代码:
var tableName = context.Model.FindEntityType(typeof(User)).SqlServer().TableName;
现在可以这么写
var tableName = context.Model.FindEntityType(typeof(User)).Relational().TableName;
更具通用性。
在比如使用方法ForSqlServerToTable
,现在可以使用更加通用的代码来实现
modelBuilder.Entity<User>().ToTable(
Database.IsSqlServer() ? "SqlServerName" : "OtherName");
请注意,此更改仅适用于为所有关系提供程序定义的API/元数据。当只针对单个提供者时,API和元数据仍然是相同的。举个例子,聚集索引是SQL Server特有的,所以ForSqlServerIsClustered
和.SqlServer().IsClustered()
必须使用。
不要控制EF服务提供程序
EF Core使用内置IServiceProvider
在框架内部实现,应用程序应该允许EF Core创建和管理这个提供程序。强烈建议删除所有UseInternalServiceProvider
的调用,AddEntityFramework
,AddEntityFrameworkSqlServer
不需要通过应用程序代码调用,建议移除。AddDbContext
的使用方式和以前一样。
内存数据库必须命名
全局匿名内存数据库已经被删除,而所有内存数据库都必须被命名。
optionsBuilder.UseInMemoryDatabase("MyDatabase");
名称相同就算调用多次,仍然使用同一个数据库,允许由多个上下文实例共享。
Read-only API 变化
IsReadOnlyBeforeSave
, IsReadOnlyAferSave
, 和 IsStoreGeneratedAlways
已经过时,由 BeforeSaveBehavior
和 AfterSaveBehavior
代替。这些行为应用到任何属性(不仅是存储生成的属性)并检测属性值如何被使用,比如插入数据库行(BeforeSaveBehavior)或更新现有数据库行(AfterSaveBehavior)。
属性通过ValueGenerated.OnAddOrUpdate
进行标记,例如:计算列。默认情况下,将忽略当前设置在该属性上的任何值。这意味着无论是否在跟踪实体上设置或修改了任何值,都将始终获得一个存储生成的值。这可以通过设置不同的Before\AfterSaveBehavior
来改变。
新的ClientSetNull删除行为
在以前的版本中DeleteBehavior.Restrict
通过上下文对实体有一个跟踪行为,这些实体与SetNull语义更加封闭。在EF Core 2.0中一个新的行为ClientSetNull
作为可选关系的默认值。此行为为跟踪实体设置了SetNull语义,并限制使用EF Core创建的数据库的行为。根据我们的经验这对跟踪实体和数据库是非常有用的。
设计时提供程序更改
Microsoft.EntityFrameworkCore.Relational.Design
引用包移除,功能被整合进Microsoft.EntityFrameworkCore.Relational
和 Microsoft.EntityFrameworkCore.Design
引用包。
不同数据设计时引用包,比如Microsoft.EntityFrameworkCore.Sqlite.Design
, Microsoft.EntityFrameworkCore.SqlServer.Design
,整合进其主提供程序中。
在EF Core 2.0中启用Scaffold-DbContext
或 dotnet ef dbcontext scaffold
现在只需要引用单一的包
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer"
Version="2.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools"
Version="2.0.0"
PrivateAssets="All" />
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet"
Version="2.0.0" />
下一步计划
已经在进行下一个版本的开发,查看开发计划,另外也在完成EF 6.2。
遗憾的地方
- 不支持GroupBy、延迟加载——这两个特性都在2.1计划中
.Net Core 2.0生态(4):Entity Framework Core 2.0 特性介绍和使用指南的更多相关文章
- Professional C# 6 and .NET Core 1.0 - Chapter 38 Entity Framework Core
本文内容为转载,重新排版以供学习研究.如有侵权,请联系作者删除. 转载请注明本文出处:Professional C# 6 and .NET Core 1.0 - Chapter 38 Entity F ...
- ASP.NET CORE系列【六】Entity Framework Core 之数据迁移
原文:ASP.NET CORE系列[六]Entity Framework Core 之数据迁移 前言 最近打算用.NET Core写一份简单的后台系统,来练练手 然后又用到了Entity Framew ...
- ASP.NET CORE系列【六】Entity Framework Core 之数据库迁移
前言 最近打算用.NET Core写一份简单的后台系统,来练练手 然后又用到了Entity Framework Core 发现园子里有些文章讲得不是那么细节,对于新手小白来说,可能会有点懵. 特意整理 ...
- Entity Framework Core系列之什么是Entity Framework Core
前言 Entity Framework Core (EF Core)是微软推荐的基于.NET Core framework的应用程序数据访问技术.它是轻量级,可扩展并且支持跨平台开发.EF Core是 ...
- Professional C# 6 and .NET Core 1.0 - 38 Entity Framework Core
本文内容为转载,重新排版以供学习研究.如有侵权,请联系作者删除. 转载请注明本文出处:Professional C# 6 and .NET Core 1.0 - 38 Entity Framework ...
- Entity Framework Core 2.0 全局查询过滤器
不定时更新翻译系列,此系列更新毫无时间规律,文笔菜翻译菜求各位看官老爷们轻喷,如觉得我翻译有问题请挪步原博客地址 本博文翻译自: http://gunnarpeipman.com/2017/08/ef ...
- ASP.NET Core 中的 ORM 之 Entity Framework
目录 EF Core 简介 使用 EF Core(Code First) EF Core 中的一些常用知识点 实体建模 实体关系 种子数据 并发管理 执行 SQL 语句和存储过程 延迟加载和预先加载 ...
- Working with Data » Getting started with ASP.NET Core and Entity Framework Core using Visual Studio » 排序、筛选、分页以及分组
Sorting, filtering, paging, and grouping 7 of 8 people found this helpful By Tom Dykstra The Contoso ...
- 浅析Entity Framework Core中的并发处理
前言 Entity Framework Core 2.0更新也已经有一段时间了,园子里也有不少的文章.. 本文主要是浅析一下Entity Framework Core的并发处理方式. 1.常见的并发处 ...
- Entity Framework Core 入门(2)
安装 EF Core 将 EF Core 添加到不同平台和常用 IDE 中的应用程序的所需步骤汇总. 分步入门教程 无需具备 Entity Framework Core 或任何特定 IDE 的原有知识 ...
随机推荐
- Chrome浏览器扩展开发系列之七:override页面
Chrome浏览器通常提供了一些默认页面,如标签管理器页面chrome://bookmarks.浏览历史记录页面chrome://history或新建Tab页面chrome://newtab等. Ch ...
- js实现单张图片(或者多张)的预览功能
这个是预览单张图片的,如果要预览多张图片,改下面红色标记的地方就好了 <html> <head> <meta http-equiv="Content-Typ ...
- 第一章:selenium + java 环境安装
1. 首先安装的是 jdk ,推荐安装的是 JDK 版本是 1.7 2. 安装 JDK 步骤: 第一步: 第二步: 第三步: 配置 JDK 环境变量,点击 我的电脑-右键-高级-环境变量. 第五 ...
- Java之面向对象例子(二)
定义一个Book类,在定义一个JavaBook类继承他 //book类 package com.hanqi.maya.model; public class Book { public String ...
- Html的基本元素(Element)
本人写这篇文章是我在IT修真园里学习了一段时间,反过来复习时整理的.虽然只是些基础知识内容,希望能帮到大家. 首先我们要了解所谓的html它的定义是什么? [html:超文本标记语言,文本:txt格式 ...
- jmeter连接配置带跳板机(SSH)的mysql服务器
jmeter连接配置mysql服务器时,如果数据库服务器没有通过ssh连接,则只需要配置相应的jdbc参数就可以了,即请求域名或ip地址:3306,如果数据库服务器是通过SSH连接的,那需要通过中间远 ...
- poj_2186: Popular Cows(tarjan基础题)
题目链接 tarjan参考博客 本文代码参考博客 题意:求在图上可以被所有点到达的点的数量. 首先通过tarjan缩点,将所有内部两两可达的子图缩为一点,新图即为一个有向无环图(即DAG). 在这个D ...
- FTP服务器 Serv-u 环境搭建
一.安装 *Windows 10 *Serv-u Windows-v15.1.2 *Mysql Mysql 5.7 安装成功后开始配置serv-u. 二.配置 1.新建域(test) 点击新建域,开始 ...
- new DefaultHttpClient过时处理建议和HTTP调用后关闭流处理
因为工作中经常会写点接口类需求,写完HTTP的接口后,就要写测试类来调下服务端的代码.最近写新的测试调用代码时候,发现项目中new DefaultHttpClient()实例过期很久了,于是查阅了些资 ...
- 学习笔记TF031:实现VGGNet
VGGNet,牛津大学计算机视觉组(Visual Geometry Group)和Google DeepMind公司一起研发,深度卷积神经网络.VGGNet反复堆叠3x3小型卷积核和2x2最大池化层, ...