EntityFramework Core 3.0查詢

前言

隨着.NET Core 3.0的發佈,EF Core 3.0也隨之正式發佈,關於這一塊最近一段時間也沒太多去關注,陸續會去對比以前版本有什麼變化沒有,本節咱們來看下兩個查詢。數據庫

分組

咱們知道在EF Core 3.0版本以前,對於分組查詢是在客戶端評估,也就是說在內存中操做,在EF Core 3.0版本後對於分組查詢能夠翻譯成SQL在數據庫進行,可是事實狀況真的是這樣嗎?接下來咱們來看下吧,以下給出代碼例子。數組

    public class EFCoreDbContext : DbContext
    {
        public EFCoreDbContext()
        {

        }
        public DbSet<Blog> Blogs { get; set; }
        public DbSet<Post> Posts { get; set; }
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        => optionsBuilder.UseSqlServer(@"Server=.;Database=EFTest;Trusted_Connection=True;");
    }

    public class Blog
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public List<Post> Posts { get; set; }
    }

    public class Post
    {
        public int Id { get; set; }
        public int BlogId { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }
        public Blog Blog { get; set; }
    }

接下來咱們在控制檯進行以下查詢:ide

            var context = new EFCoreDbContext();

            var posts = context.Posts.GroupBy(d => d.BlogId)
                .Select(g => new 
                {
                    id = g.Key,
                    count = g.Count()
                })
                .ToList();

上述咱們查詢每一篇博客的文章數組,咱們經過SQL Profiler跟蹤到上述示例代碼最終翻譯成的SQL如咱們所指望的那樣,以下圖:post

假設如今有這樣一個場景:查詢全部博客發表的第一篇博客文章。基於這種場景咱們須要對發表博客文章進行分組,而後取第一篇,因此接下來咱們進行以下查詢:ui

            var context = new EFCoreDbContext();

            var posts = context.Posts.GroupBy(d => d.BlogId)
                .Select(g => g.FirstOrDefault())
                .ToList();

既然這樣沒法翻譯,根據官方文檔可使用Linq to Object進行查詢《https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-3.0/》 ,那麼咱們就修改爲以下代碼查詢看看:spa

            var context = new EFCoreDbContext();

            var posts = context.Posts.GroupBy(d => d.BlogId).AsEnumerable()
                .Select(d => d.FirstOrDefault())
                .ToList();

咋客戶端都沒法支持了呢?咱們只是想查詢全部博客列表中第一篇文章,按照咱們的理解,理論上是能夠進行翻譯的對不對,好比翻譯成以下直接寫的SQL語句:翻譯

SELECT 
    Id,BlogId,Title,Content 
FROM (
  SELECT *
      ,ROW_NUMBER() OVER (
                     PARTITION BY BlogId 
                     ORDER BY Id
                ) AS [ROW NUMBER]
  FROM dbo.Posts
  ) groups
WHERE groups.[ROW NUMBER] = 1
ORDER BY groups.Id DESC

因此到這裏咱們大概能夠猜想出EF Core對分組查詢支持的並非那麼好,目前應該只支持簡單的分組求和而已,稍微複雜一點則沒法翻譯,因此咱們仍是老老實實將分組仍是徹底放在客戶端評估吧,以下:code

            var context = new EFCoreDbContext();

            var posts = context.Posts.ToList().GroupBy(d => d.BlogId)
                .Select(d => d.FirstOrDefault())
                .ToList();

 

查找

咱們能夠經過 EF.Functions.Like 來進行模糊查詢,咱們能夠經過StartWith或EndWith來查詢開頭或結尾的數據,要是如今須要查詢出博客文章標題中包含某一字符的文章列表,咱們又該如何查詢呢?咱們想到經過IndexOf來查詢,接下來咱們來看看:blog

            var context = new EFCoreDbContext();

            var posts = context.Posts.Where(d => d.Title.IndexOf('C') == 2).ToList();

難道咱們又只能將全部查詢出來,而後在內存中操做嗎?代碼以下:索引

            var context = new EFCoreDbContext();

            var posts = context.Posts.ToList().Where(d => d.Title.IndexOf('C') == 2).ToList();

其實咱們只要將上述單引號修改雙引號便可解決徹底在客戶端評估的問題,以下:

            var context = new EFCoreDbContext();

            var posts = context.Posts.Where(d => d.Title.IndexOf("C") == 2).ToList();

根據咱們的查詢描述,咱們明明是想查詢在標題中查詢指定字符,爲什麼對字符不能支持,只支持字符串呢,不知道官方是出於何種緣由。同時這裏咱們也注意到,不管是MySQL仍是SQL Server等等,儘可能不要將表中列設置爲可空,即便是可空也要設置爲不可空,給定一個默認值便可,一旦數據量巨大時,會發現查詢很慢,由於經過IS NULL或者IS NOT NULL不走索引致使。好比上述咱們查詢的Title,咱們不管是經過Data Annotations仍是Fluent Api,都必須配置成不可空,好比這裏咱們經過Data Annotations配置以下:

        [Required]
        public string Title { get; set; }

此時咱們繼續進行上述查詢時候,會發現對空值的判斷已經沒有了,同時也減小了查詢語句,以下:

總結

請注意上述我所演示EF Core版本爲3.0.1。本節我也只是經過簡單的示例稍微給你們看了EF Core 3中一些小的問題,固然可能還存在其餘的問題,更多細節等我後續研究會繼續給出EF Core 3.x系列文章,感謝您的閱讀,如有敘述不當或錯誤之處,還望指正,謝謝。

相關文章
相關標籤/搜索