前言

这是.Net Core 2.0生态生态介绍的最后一篇,EF一直是我喜欢的一个ORM框架,随着版本升级EF也发展到EF6.x,Entity Framework Core是一个支持跨平台的全新版本,可以用三个词来概况EF Core的特点:轻量级、可扩展、跨平台。跨平台的特性是EF6.x无法替代的优势,也许会成为你在项目中技术选型的原因之一。

对于.NET Core 2.0的发布介绍,围绕2.0的架构体系,本系列相关文章:

  1. .Net Core 2.0 生态(1).NET Standard 2.0 特性介绍和使用指南(已发布)
  2. .Net Core 2.0 生态(2).NET Core 2.0 特性介绍和使用指南(已发布)
  3. .Net Core 2.0 生态(3)ASP.NET Core 2.0 特性介绍和使用指南(已发布)
  4. .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变化

  1. 将项目.NET平台设置为支持.NET Standard 2.0的平台
  2. 使用支持2.0的数据库提供程序
  3. 更新EF Core引用包(包括运行时和工具)到2.0
  4. 必要的时候对代码进行修改,具体参看核心变化

在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-Databasedotnet 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的调用,AddEntityFrameworkAddEntityFrameworkSqlServer不需要通过应用程序代码调用,建议移除。AddDbContext的使用方式和以前一样。

内存数据库必须命名

全局匿名内存数据库已经被删除,而所有内存数据库都必须被命名。

optionsBuilder.UseInMemoryDatabase("MyDatabase");

名称相同就算调用多次,仍然使用同一个数据库,允许由多个上下文实例共享。

Read-only API 变化

IsReadOnlyBeforeSave, IsReadOnlyAferSave, 和 IsStoreGeneratedAlways 已经过时,由 BeforeSaveBehaviorAfterSaveBehavior代替。这些行为应用到任何属性(不仅是存储生成的属性)并检测属性值如何被使用,比如插入数据库行(BeforeSaveBehavior)或更新现有数据库行(AfterSaveBehavior)。

属性通过ValueGenerated.OnAddOrUpdate进行标记,例如:计算列。默认情况下,将忽略当前设置在该属性上的任何值。这意味着无论是否在跟踪实体上设置或修改了任何值,都将始终获得一个存储生成的值。这可以通过设置不同的Before\AfterSaveBehavior来改变。

新的ClientSetNull删除行为

在以前的版本中DeleteBehavior.Restrict通过上下文对实体有一个跟踪行为,这些实体与SetNull语义更加封闭。在EF Core 2.0中一个新的行为ClientSetNull作为可选关系的默认值。此行为为跟踪实体设置了SetNull语义,并限制使用EF Core创建的数据库的行为。根据我们的经验这对跟踪实体和数据库是非常有用的。

设计时提供程序更改

Microsoft.EntityFrameworkCore.Relational.Design引用包移除,功能被整合进Microsoft.EntityFrameworkCore.RelationalMicrosoft.EntityFrameworkCore.Design引用包。

不同数据设计时引用包,比如Microsoft.EntityFrameworkCore.Sqlite.Design, Microsoft.EntityFrameworkCore.SqlServer.Design,整合进其主提供程序中。

在EF Core 2.0中启用Scaffold-DbContextdotnet 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 特性介绍和使用指南的更多相关文章

  1. 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 ...

  2. ASP.NET CORE系列【六】Entity Framework Core 之数据迁移

    原文:ASP.NET CORE系列[六]Entity Framework Core 之数据迁移 前言 最近打算用.NET Core写一份简单的后台系统,来练练手 然后又用到了Entity Framew ...

  3. ASP.NET CORE系列【六】Entity Framework Core 之数据库迁移

    前言 最近打算用.NET Core写一份简单的后台系统,来练练手 然后又用到了Entity Framework Core 发现园子里有些文章讲得不是那么细节,对于新手小白来说,可能会有点懵. 特意整理 ...

  4. Entity Framework Core系列之什么是Entity Framework Core

    前言 Entity Framework Core (EF Core)是微软推荐的基于.NET Core framework的应用程序数据访问技术.它是轻量级,可扩展并且支持跨平台开发.EF Core是 ...

  5. Professional C# 6 and .NET Core 1.0 - 38 Entity Framework Core

    本文内容为转载,重新排版以供学习研究.如有侵权,请联系作者删除. 转载请注明本文出处:Professional C# 6 and .NET Core 1.0 - 38 Entity Framework ...

  6. Entity Framework Core 2.0 全局查询过滤器

    不定时更新翻译系列,此系列更新毫无时间规律,文笔菜翻译菜求各位看官老爷们轻喷,如觉得我翻译有问题请挪步原博客地址 本博文翻译自: http://gunnarpeipman.com/2017/08/ef ...

  7. ASP.NET Core 中的 ORM 之 Entity Framework

    目录 EF Core 简介 使用 EF Core(Code First) EF Core 中的一些常用知识点 实体建模 实体关系 种子数据 并发管理 执行 SQL 语句和存储过程 延迟加载和预先加载 ...

  8. 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 ...

  9. 浅析Entity Framework Core中的并发处理

    前言 Entity Framework Core 2.0更新也已经有一段时间了,园子里也有不少的文章.. 本文主要是浅析一下Entity Framework Core的并发处理方式. 1.常见的并发处 ...

  10. Entity Framework Core 入门(2)

    安装 EF Core 将 EF Core 添加到不同平台和常用 IDE 中的应用程序的所需步骤汇总. 分步入门教程 无需具备 Entity Framework Core 或任何特定 IDE 的原有知识 ...

随机推荐

  1. Chrome浏览器扩展开发系列之七:override页面

    Chrome浏览器通常提供了一些默认页面,如标签管理器页面chrome://bookmarks.浏览历史记录页面chrome://history或新建Tab页面chrome://newtab等. Ch ...

  2. js实现单张图片(或者多张)的预览功能

      这个是预览单张图片的,如果要预览多张图片,改下面红色标记的地方就好了 <html> <head> <meta http-equiv="Content-Typ ...

  3. 第一章:selenium + java 环境安装

    1. 首先安装的是 jdk ,推荐安装的是   JDK 版本是 1.7 2.  安装 JDK 步骤: 第一步: 第二步: 第三步: 配置 JDK 环境变量,点击 我的电脑-右键-高级-环境变量. 第五 ...

  4. Java之面向对象例子(二)

    定义一个Book类,在定义一个JavaBook类继承他 //book类 package com.hanqi.maya.model; public class Book { public String ...

  5. Html的基本元素(Element)

    本人写这篇文章是我在IT修真园里学习了一段时间,反过来复习时整理的.虽然只是些基础知识内容,希望能帮到大家. 首先我们要了解所谓的html它的定义是什么? [html:超文本标记语言,文本:txt格式 ...

  6. jmeter连接配置带跳板机(SSH)的mysql服务器

    jmeter连接配置mysql服务器时,如果数据库服务器没有通过ssh连接,则只需要配置相应的jdbc参数就可以了,即请求域名或ip地址:3306,如果数据库服务器是通过SSH连接的,那需要通过中间远 ...

  7. poj_2186: Popular Cows(tarjan基础题)

    题目链接 tarjan参考博客 本文代码参考博客 题意:求在图上可以被所有点到达的点的数量. 首先通过tarjan缩点,将所有内部两两可达的子图缩为一点,新图即为一个有向无环图(即DAG). 在这个D ...

  8. FTP服务器 Serv-u 环境搭建

    一.安装 *Windows 10 *Serv-u Windows-v15.1.2 *Mysql Mysql 5.7 安装成功后开始配置serv-u. 二.配置 1.新建域(test) 点击新建域,开始 ...

  9. new DefaultHttpClient过时处理建议和HTTP调用后关闭流处理

    因为工作中经常会写点接口类需求,写完HTTP的接口后,就要写测试类来调下服务端的代码.最近写新的测试调用代码时候,发现项目中new DefaultHttpClient()实例过期很久了,于是查阅了些资 ...

  10. 学习笔记TF031:实现VGGNet

    VGGNet,牛津大学计算机视觉组(Visual Geometry Group)和Google DeepMind公司一起研发,深度卷积神经网络.VGGNet反复堆叠3x3小型卷积核和2x2最大池化层, ...