前言
本节我们再来讲讲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中相关数据加载的三种模式以及对于客户端数据能够进行简单的翻译,我们下节再见。