前言
本節我們再來講講EF Core,本節算是回歸基礎吧,當前項目EF Core還是處於1.1版本中,后續等待.net core等版本穩定了全部會更新到2.0版本中,到時再來更新相關文章分享給大家。
相關數據加載
在EF中一直以來都是通過導航屬性來加載一個實體的相關數據,在EF Core中加載相關數據有以下三種模式:
飢餓加載
來自數據庫相關聯數據的加載也會作為實體的一部分進行加載。
我們通過Include方法來進行飢餓加載實體相關聯的數據,如下:
using (var context = new BloggingContext()) { var blogs = context.Blogs .Include(blog => blog.Posts) .ToList(); }
當然我們也可以同時關聯實體的多個屬性,如下:
using (var context = new BloggingContext()) { var blogs = context.Blogs .Include(blog => blog.Posts) .Include(blog => blog.Owner) .ToList(); }
同時我們也可以類似層級一樣來加載一個實體的相關的實體的相關聯實體,通過ThenInclude,如下:
using (var context = new BloggingContext()) { var blogs = context.Blogs .Include(blog => blog.Posts) .ThenInclude(post => post.Author) .ToList(); }
是不是只要我們加上了Include方法就會加載一個實體相關聯的數據呢,如下:
using (var context = new BloggingContext()) { var blogs = context.Blogs .Include(blog => blog.Posts) .Select(blog => new { Id = blog.BlogId, Url = blog.Url }) .ToList(); }
很明顯我們最后只是投影了Blog中的幾個字段,所以此時會忽略對Post導航屬性的查詢。當在這種情況下對於最后返回的數據未包含相關聯數據時在日志文件中會進行提醒,在這種情況下我們很明確知道會忽略對導航數據的加載,同時也不會拋出異常,我們可以在日志文件中對該項處理進行忽略,如下:
services.AddDbContext<EFCoreContext>(options => { options.UseSqlServer(sqlStr, d => d.MigrationsAssembly("StudyEFCore")) .ConfigureWarnings(warnings => warnings.Throw(CoreEventId.IncludeIgnoredWarning); });
顯式加載
來自數據庫相關聯數據的加載在稍后會進行加載。
顯式加載只有在EF Core1.1版本上才會被支持,通過DbContext.Entry()來實現,如下:
using (var context = new BloggingContext()) { var blog = context.Blogs .Single(b => b.BlogId == 1); context.Entry(blog) .Collection(b => b.Posts) .Load(); context.Entry(blog) .Reference(b => b.Owner) .Load(); }
當然我們也可以通過Linq來加載相關聯數據,如下:
using (var context = new BloggingContext()) { var blog = context.Blogs .Single(b => b.BlogId == 1); var postCount = context.Entry(blog) .Collection(b => b.Posts) .Query() .Count(); }
延遲加載
來自數據庫相關聯數據的加載當導航屬性被訪問時會被加載,在EF Core中可能將會實現。
客戶端數據評估進行翻譯
在EF Core中不像之前EF版本對於在lambda表達式中對數據進行操作此時將導致無法翻譯從而出錯,但是在EF Core中對於一些簡單的數據可以進行了翻譯,這一點還是讓我們有了一點期待。我們一起來看看。
public class Sample { public static string StandardizeUrl(string url) { url = url.ToLower(); if (!url.StartsWith("http://")) { url = string.Concat("http://", url); } return url; } public static void Run() { using (var context = new BloggingContext()) { var blogs = context.Blogs .OrderByDescending(blog => blog.Rating) .Select(blog => new { Id = blog.BlogId, Url = StandardizeUrl(blog.Url) }) .ToList(); } using (var context = new BloggingContext()) { var blogs = context.Blogs .Where(blog => StandardizeUrl(blog.Url).Contains("dotnet")) .ToList(); } } }
同時這種對於代碼進行評估進行翻譯的情況我們也可以進行禁用,如下:
services.AddDbContext<EFCoreContext>(options => { options.UseSqlServer(sqlStr, d => d.MigrationsAssembly("StudyEFCore")) .ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning)); });
總結
本文簡單講解了下EF Core中相關數據加載的三種模式以及對於客戶端數據能夠進行簡單的翻譯,我們下節再見。