前言
这是.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
(
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 'IDesignTimeDb