Entity Framework Core 2.0 特性介绍和使用指南
前言
這是.Net Core 2.0生態(tài)生態(tài)介紹的最后一篇,EF一直是我喜歡的一個(gè)ORM框架,隨著版本升級(jí)EF也發(fā)展到EF6.x,Entity Framework Core是一個(gè)支持跨平臺(tái)的全新版本,可以用三個(gè)詞來(lái)概況EF Core的特點(diǎn):輕量級(jí)、可擴(kuò)展、跨平臺(tái)。跨平臺(tái)的特性是EF6.x無(wú)法替代的優(yōu)勢(shì),也許會(huì)成為你在項(xiàng)目中技術(shù)選型的原因之一。
獲取和使用
在命令行工具安裝NuGet包,比如:安裝SQL Server EF Core提供程序,并指定版本為2.0.0。
$ dotnet add package Microsoft.EntityFrameworkCore.SqlServer -V 2.0.0在VS2017中使用包管理器控制臺(tái)安裝
PM> Install-Package Microsoft.EntityFrameworkCore.SqlServer -Version 2.0.0在ASP.NET Core 2.0默認(rèn)項(xiàng)目包含支持EF Core 2.0的SQL Server, SQLite, 和 in-memory數(shù)據(jù)庫(kù)提供程序,創(chuàng)建項(xiàng)目無(wú)需額外添加。
查看在不同平臺(tái)上使用EF Core指南,查看更多安裝和升級(jí)細(xì)節(jié),進(jìn)入幫助文檔。
新特性
以下是最顯著的新特性:
使用.NET Standard 2.0目標(biāo)框架:這使得EF Core 2.0可支持多種.NET平臺(tái)實(shí)現(xiàn)和應(yīng)用程序類(lèi)型,查看平臺(tái)支持列表。
LINQ解析改進(jìn):EF Core 2.0中的查詢更加高效,適應(yīng)多種場(chǎng)景。舉個(gè)例子,增加了翻譯成SQL語(yǔ)句模式的數(shù)量限制,避免了在以前版本中因?yàn)榭蛻舳擞?jì)算導(dǎo)致多重查詢的問(wèn)題。(優(yōu)化了客戶端計(jì)算性能)
Like查詢支持:LINQ查詢可以使用EF.Functions.Like(),最終解析為SQL中的like語(yǔ)句,在必要的時(shí)候會(huì)進(jìn)行內(nèi)存計(jì)算,舉個(gè)例子,下面的查詢:
var customers =
from c in context.Customers
where EF.Functions.Like(c.Name, "a%");
select c;
解析成SQL語(yǔ)句:
?SELECT [c].[Id], [c].[Name] ?FROM [Customers] AS [c] ?WHERE [c].[Name] LIKE N'a%';和SQL中l(wèi)ike語(yǔ)句一樣使用通配符。
實(shí)體包含關(guān)系和表拆分:可以通過(guò)屬性關(guān)聯(lián)建立實(shí)體之間的包含關(guān)系,這個(gè)特性和EF6中的復(fù)合類(lèi)型類(lèi)似,只需要定義一個(gè)導(dǎo)航屬性。實(shí)體包含關(guān)系定義與表拆分結(jié)合使用,可以將兩個(gè)實(shí)體自動(dòng)映射為單張表,參看下面的示例:
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);
全局查詢過(guò)濾器:在DbContext中為實(shí)體定義查詢過(guò)濾器,下面代碼在OnModelCreating方法中定義:
modelBuilder.Entity<Post>() .HasQueryFilter(p => !p.IsDeleted);
下面的查詢只會(huì)返回未被標(biāo)記為刪除的結(jié)果:
?var blog = context.Blogs.Include(b => b.Posts).FirstOrDefault(b => b.Id == id);這個(gè)特性在特殊的業(yè)務(wù)場(chǎng)景下將有大用處,比如多租戶中數(shù)據(jù)過(guò)濾實(shí)現(xiàn)。
DbContext Pooling(池):這項(xiàng)特性能夠顯著提升Asp.net Core應(yīng)用程序的性能,通過(guò)在服務(wù)注冊(cè)DbContext類(lèi)型時(shí)啟用,使用預(yù)先創(chuàng)建的實(shí)例池,避免為每個(gè)請(qǐng)求創(chuàng)建新實(shí)例:
services.AddDbContextPool (
options => options.UseSqlServer(connectionString));這是一個(gè)最佳實(shí)踐,推薦使用!
SQL方法支持字符串插值:下面的SQL語(yǔ)句使用了C#中字符串插值語(yǔ)法,簡(jiǎn)化參數(shù)化查詢:
var city = "Redmond";- using (var context = CreateContext())
- {context.Customers.FromSql($@" ? ? ? ?SELECT * ? ? ? ?FROM Customers ? ? ? ?WHERE City = {city}"); }
以上代碼轉(zhuǎn)換為SQL語(yǔ)句會(huì)創(chuàng)建一個(gè)名為@p0的參數(shù),值為Redmond,生成如下SQL語(yǔ)句:
? ?SELECT * ? ?FROM Customers ? ?WHERE City = @p0更多特性:如:顯式編譯查詢、自包含實(shí)體配置、數(shù)據(jù)庫(kù)標(biāo)準(zhǔn)函數(shù)映射。還修復(fù)了許多Bug。詳細(xì)內(nèi)容參考:新功能
項(xiàng)目升級(jí)和核心API變化
將項(xiàng)目.NET平臺(tái)設(shè)置為支持.NET Standard 2.0的平臺(tái)
使用支持2.0的數(shù)據(jù)庫(kù)提供程序
更新EF Core引用包(包括運(yùn)行時(shí)和工具)到2.0
必要的時(shí)候?qū)Υa進(jìn)行修改,具體參看核心變化
在2.0版本中,部分API和操作有較大該井,有部分改進(jìn)需要修改現(xiàn)有程序代碼,對(duì)于大多數(shù)應(yīng)用程序來(lái)說(shuō),影響不大,大多數(shù)情況下,只需要重新編譯和最少的修改來(lái)替換過(guò)時(shí)的API。
獲取應(yīng)用程序服務(wù)新方式
注:EF Core在設(shè)計(jì)時(shí)的操作比如生成數(shù)據(jù)遷移代碼,更新數(shù)據(jù)庫(kù),需要訪問(wèn)應(yīng)用程序服務(wù)。設(shè)計(jì)時(shí)工具和應(yīng)用程序存在調(diào)用關(guān)系。
推薦將ASP.NET Core Web應(yīng)用程序更新到2.0,在ASP.NET Core 2.0在啟動(dòng)類(lèi)之外初始化配置。在之前的版本EF Core嘗試執(zhí)行Startup.ConfigureServices,直接訪問(wèn)應(yīng)用程序的服務(wù)提供者,使用EF Core的應(yīng)用程序通常從配置文件中訪問(wèn)連接字符串,所以單靠Startup已經(jīng)不能滿足獲取連接字符串的需要。
更新ASP.NET Core 1.x到2.0,當(dāng)使用了EF Core工具,會(huì)收到如下錯(cuò)誤提示:
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默認(rèn)模板中新增設(shè)計(jì)時(shí)支持,靜態(tài)方法Program.BuildWebHost允許EF Core在設(shè)計(jì)時(shí)訪問(wèn)應(yīng)用程序服務(wù)提供者,如果升級(jí)ASP.NET Core 1.x應(yīng)用程序,同時(shí)升級(jí)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();} }
注:如果沒(méi)有ASP.NET Core 2.0應(yīng)用程序沒(méi)有更改Program啟動(dòng)方式,依然可以使用實(shí)現(xiàn)IDesignTimeDbContextFactory<ApplicationContext>接口方式提供EF Core 2.0設(shè)計(jì)時(shí)支持,不推薦這么做。
IDbContextFactory改名
為了支持不同的應(yīng)用模式,在設(shè)計(jì)時(shí)提供對(duì)DbContext更多自定義控制,在以前的版本提供接口IDbContextFactory<TContext>,EF Core工具在設(shè)計(jì)時(shí),會(huì)發(fā)現(xiàn)應(yīng)用程序中該接口的實(shí)現(xiàn)并使用它來(lái)創(chuàng)建DbContext對(duì)象。
這個(gè)接口因?yàn)榫哂型ㄓ眯缘拿Q,容易誤導(dǎo)開(kāi)發(fā)者使用來(lái)處理需要重新創(chuàng)建DbContext的開(kāi)發(fā)場(chǎng)景,當(dāng)在設(shè)計(jì)時(shí)EF Core工具使用它時(shí)因?yàn)闆](méi)有考慮到設(shè)計(jì)時(shí)的特殊環(huán)境可以導(dǎo)致Update-Database或dotnet ef database update命令執(zhí)行失敗。
基于以上的原因,為了更精準(zhǔn)的表達(dá)該接口的作用,我們將其改名為IDesignTimeDbContextFactory<TContext>,在2.0中IDbContextFactory<TContext>仍然存在,但是已經(jīng)標(biāo)記為過(guò)時(shí)了。
DbContextFactoryOptions移除
因?yàn)锳SP.NET 2.0的升級(jí),我們發(fā)現(xiàn)在接口IDesignTimeDbContextFactory<TContext>不在需要DbContextFactoryOptions。
下面是你應(yīng)該使用的替代方案。
DbContextFactoryOptions.ApplicationBasePath 使用AppContext.BaseDirectory代替
DbContextFactoryOptions.ContentRootPath 使用Directory.GetCurrentDirectory()代替
DbContextFactoryOptions.EnvironmentName 使用Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")代替
EF Core 2.0需要2.0數(shù)據(jù)庫(kù)提供程序
對(duì)于EF Core 2.0,我們已經(jīng)對(duì)數(shù)據(jù)庫(kù)提供程序的工作進(jìn)行了許多簡(jiǎn)化和改進(jìn)。1.0.x和1.1.x提供程序已經(jīng)不能在EF Core 2.0下工作。
由EF團(tuán)隊(duì)開(kāi)發(fā)的SQL Server和SQLite數(shù)據(jù)庫(kù)提供程序,2.0版本將在2.0版本中提供。其他數(shù)據(jù)庫(kù)提供程序也已經(jīng)升級(jí)到2.0版本:
SQL Compact
PostgreSQL
MySQL
日志記錄和診斷事件更改
注意:這些更改不會(huì)影響大多數(shù)的應(yīng)用程序代碼。
發(fā)送給ILogger的消息的事件ID在2.0中發(fā)生了變化。現(xiàn)在在EF Core中事件ID是全局唯一的。這些消息現(xiàn)在也遵循了結(jié)構(gòu)化日志的標(biāo)準(zhǔn)模式,例如,MVC。
Logger類(lèi)別也發(fā)生了變化,類(lèi)別可通過(guò)DbLoggerCategory訪問(wèn)。
DiagnosticSource事件現(xiàn)在使用與對(duì)應(yīng)ILogger消息相同的時(shí)間ID名稱,事件ID、有效負(fù)載類(lèi)型和類(lèi)別進(jìn)行了統(tǒng)一。
ID從Microsoft.EntityFrameworkCore.Infraestructure命名空間移到Microsoft.EntityFrameworkCore.Diagnostics。
EF Core元數(shù)據(jù)關(guān)系A(chǔ)PI變化
EF Core 2.0為不同的提供程序創(chuàng)建一個(gè)不同的IModel,這通常對(duì)應(yīng)用程序是透明的,從而簡(jiǎn)化了底層元數(shù)據(jù)API,使得任何對(duì)公共關(guān)系的元數(shù)據(jù)都可以通過(guò)調(diào)用來(lái)實(shí)現(xiàn),對(duì)比如下代碼,在1.1.x中代碼:
var tableName = context.Model.FindEntityType(typeof(User)).SqlServer().TableName;現(xiàn)在可以這么寫(xiě)
var tableName = context.Model.FindEntityType(typeof(User)).Relational().TableName;更具通用性。
在比如使用方法ForSqlServerToTable,現(xiàn)在可以使用更加通用的代碼來(lái)實(shí)現(xiàn)
modelBuilder.Entity<User>().ToTable(Database.IsSqlServer() ? "SqlServerName" : "OtherName");請(qǐng)注意,此更改僅適用于為所有關(guān)系提供程序定義的API/元數(shù)據(jù)。當(dāng)只針對(duì)單個(gè)提供者時(shí),API和元數(shù)據(jù)仍然是相同的。舉個(gè)例子,聚集索引是SQL Server特有的,所以ForSqlServerIsClustered和.SqlServer().IsClustered()必須使用。
不要控制EF服務(wù)提供程序
EF Core使用內(nèi)置IServiceProvider在框架內(nèi)部實(shí)現(xiàn),應(yīng)用程序應(yīng)該允許EF Core創(chuàng)建和管理這個(gè)提供程序。強(qiáng)烈建議刪除所有UseInternalServiceProvider的調(diào)用,AddEntityFramework,AddEntityFrameworkSqlServer不需要通過(guò)應(yīng)用程序代碼調(diào)用,建議移除。AddDbContext的使用方式和以前一樣。
內(nèi)存數(shù)據(jù)庫(kù)必須命名
全局匿名內(nèi)存數(shù)據(jù)庫(kù)已經(jīng)被刪除,而所有內(nèi)存數(shù)據(jù)庫(kù)都必須被命名。
optionsBuilder.UseInMemoryDatabase("MyDatabase");名稱相同就算調(diào)用多次,仍然使用同一個(gè)數(shù)據(jù)庫(kù),允許由多個(gè)上下文實(shí)例共享。
Read-only API 變化
IsReadOnlyBeforeSave,?IsReadOnlyAferSave, 和?IsStoreGeneratedAlways?已經(jīng)過(guò)時(shí),由?BeforeSaveBehavior?和?AfterSaveBehavior代替。這些行為應(yīng)用到任何屬性(不僅是存儲(chǔ)生成的屬性)并檢測(cè)屬性值如何被使用,比如插入數(shù)據(jù)庫(kù)行(BeforeSaveBehavior)或更新現(xiàn)有數(shù)據(jù)庫(kù)行(AfterSaveBehavior)。
屬性通過(guò)ValueGenerated.OnAddOrUpdate進(jìn)行標(biāo)記,例如:計(jì)算列。默認(rèn)情況下,將忽略當(dāng)前設(shè)置在該屬性上的任何值。這意味著無(wú)論是否在跟蹤實(shí)體上設(shè)置或修改了任何值,都將始終獲得一個(gè)存儲(chǔ)生成的值。這可以通過(guò)設(shè)置不同的Before\AfterSaveBehavior來(lái)改變。
新的ClientSetNull刪除行為
在以前的版本中DeleteBehavior.Restrict通過(guò)上下文對(duì)實(shí)體有一個(gè)跟蹤行為,這些實(shí)體與SetNull語(yǔ)義更加封閉。在EF Core 2.0中一個(gè)新的行為ClientSetNull作為可選關(guān)系的默認(rèn)值。此行為為跟蹤實(shí)體設(shè)置了SetNull語(yǔ)義,并限制使用EF Core創(chuàng)建的數(shù)據(jù)庫(kù)的行為。根據(jù)我們的經(jīng)驗(yàn)這對(duì)跟蹤實(shí)體和數(shù)據(jù)庫(kù)是非常有用的。
設(shè)計(jì)時(shí)提供程序更改
Microsoft.EntityFrameworkCore.Relational.Design引用包移除,功能被整合進(jìn)Microsoft.EntityFrameworkCore.Relational?和?Microsoft.EntityFrameworkCore.Design引用包。
不同數(shù)據(jù)設(shè)計(jì)時(shí)引用包,比如Microsoft.EntityFrameworkCore.Sqlite.Design,?Microsoft.EntityFrameworkCore.SqlServer.Design,整合進(jìn)其主提供程序中。
在EF Core 2.0中啟用Scaffold-DbContext?或?dotnet ef dbcontext scaffold?現(xiàn)在只需要引用單一的包
<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" />下一步計(jì)劃
已經(jīng)在進(jìn)行下一個(gè)版本的開(kāi)發(fā),查看開(kāi)發(fā)計(jì)劃,另外也在完成EF 6.2。
遺憾的地方
不支持GroupBy、延遲加載——這兩個(gè)特性都在2.1計(jì)劃中
相關(guān)文章:?
.NET Core 2.0 正式發(fā)布信息匯總
.NET Standard 2.0 特性介紹和使用指南
.NET Core 2.0 的dll實(shí)時(shí)更新、https、依賴包變更問(wèn)題及解決
.NET Core 2.0 特性介紹和使用指南
Entity Framework Core 2.0 新特性
體驗(yàn) PHP under .NET Core
.NET Core 2.0使用NLog
升級(jí)項(xiàng)目到.NET Core 2.0,在Linux上安裝Docker,并成功部署
解決Visual Studio For Mac Restore失敗的問(wèn)題
ASP.NET Core 2.0 特性介紹和使用指南
原文地址:http://www.cnblogs.com/YGYH/p/7416275.html
.NET社區(qū)新聞,深度好文,微信中搜索dotNET跨平臺(tái)或掃描二維碼關(guān)注
總結(jié)
以上是生活随笔為你收集整理的Entity Framework Core 2.0 特性介绍和使用指南的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 迁移.net framework 工程到
- 下一篇: Orleans简单配置