1. 程式人生 > >EntityFramework Core數據查詢

EntityFramework Core數據查詢

出錯 alua configure ons options blog 對數 pub 再見

前言

本節我們再來講講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中相關數據加載的三種模式以及對於客戶端數據能夠進行簡單的翻譯,我們下節再見。

EntityFramework Core數據查詢