.Net 性能優化--EFCore(EntityFrameworkCore)


新建.NET CORE CONSOLE控制台項目NetCoreConsole,管理NuGet程序包種添加一下引用

//Microsoft.EntityFrameworkCore //EFCore 
//Microsoft.Extensions.Logging  // 日志
//Microsoft.Extensions.Logging.Console // 日志輸出到Console控制台
//Microsoft.Extensions.Logging.Debug  // 日志輸出到調試Debug
//Microsoft.EntityFrameworkCore.Proxies// 懶加載,延遲加載,EFCore沒有懶加載,使用該庫,可以實現懶加載
//Microsoft.EntityFrameworkCore.SqlServer//EFCore使用的SqlServer數據庫
//Pomelo.EntityFrameworkCore.MySql//EFCore使用的MySql數據庫

項目代碼如下:

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
using System.Linq;
using System.Diagnostics;
using Microsoft.EntityFrameworkCore.Storage;

//Microsoft.EntityFrameworkCore //EFCore 
//Microsoft.Extensions.Logging  // 日志
//Microsoft.Extensions.Logging.Console // 日志輸出到Console控制台
//Microsoft.Extensions.Logging.Debug  // 日志輸出到調試Debug
//Microsoft.EntityFrameworkCore.Proxies// 懶加載,延遲加載,EFCore沒有懶加載,使用該庫,可以實現懶加載
//Microsoft.EntityFrameworkCore.SqlServer//EFCore使用的SqlServer數據庫
//Pomelo.EntityFrameworkCore.MySql//EFCore使用的MySql數據庫
namespace NetCoreConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("測試  EF core ");
            BlogContext blogContext = new BlogContext();

            #region ef 數據庫的創建和刪除
            //Console.WriteLine("刪除數據庫");
            //blogContext.Database.EnsureDeleted();
            //Console.WriteLine("添加數據庫");            
            blogContext.Database.EnsureCreated();
            //Console.WriteLine("添加數據庫成功"); 
            #endregion

            #region 數據遷移相關
            //IEnumerable<string> vs = blogContext.Database.GetMigrations();
            //blogContext.Database.GetPendingMigrations();
            //blogContext.Database.GetAppliedMigrations();
            //blogContext.Database.Migrate(); 
            //Console.WriteLine("添加數據庫成功");
            #endregion

            #region 預先加載,懶加載

            //預先加載(貪婪加載,飢餓加載,一次行加載所有)
            //var list = blogContext.Blog.Include(op => op.Posts).ThenInclude(op => op.Author).ToList();
            //var list = blogContext.Blog.Include(op => op.Posts).ThenInclude(op => op.Author).ToList();
            //var list = blogContext.Blog.Include(op => op.Posts).ThenInclude(op => op.Author).ToList().AsQueryable();
            //foreach (var item in list)
            //{
            //    Console.WriteLine($"blog:{item}");
            //    foreach (var it in item.Posts)
            //    {
            //        Console.WriteLine($"Posts:{it.Title}");
            //        Console.WriteLine($"person:{it.Author.Name}");
            //    }
            //}
            //懶加載(延遲加載),又稱按需加載,net ef core 默認時候沒有懶加載的,
            //ef是有的,ef core 要使用懶加載,需要使用proxy代理類UseLazyLoadingProxies,並且導航屬性要添加Virtual標記
            //optionsBuilder.UseLazyLoadingProxies() 
            #endregion

            #region IQueryable和IEnumerable不同
            //IQueryable和IEnumerable不同
            //IQueryable和IEnumerable都是linq操作
            //IQueryable和IEnumerable都是延遲執行,tolist的時候在執行
            //只不過操作的位置不同,IQueryable是在數據庫一側操作,而IEnumerable實在應用程序的內存一側操作,
            //IQueryable繼承IEnumerable,IQueryable與IEnumerable 可以相互轉換,IQueryable.AsIEnumerable,IEnumerable.AsIQueryable
            //var item = blogContext.Post.OrderBy(op => EF.Property<object>(op, "Title")).AsQueryable().Skip(1).Take(2);
            //IQueryable 在數據庫中的 執行腳本,IQueryable和IEnumerable都是延遲執行,tolist的時候在執行
            //exec sp_executesql N'SELECT [p].[PostId], [p].[BlogId], [p].[Content], [p].[PersonId], [p].[Title]
            //FROM[Post] AS[p]
            //ORDER BY[p].[Title]
            //OFFSET @__p_0 ROWS FETCH NEXT @__p_1 ROWS ONLY',N'@__p_0 int,@__p_1 int',@__p_0=1,@__p_1=2

            //foreach (var it in item)
            //{
            //    Console.WriteLine($"it:{it.Title}");
            //}

            //var item = blogContext.Post.OrderBy(op => op.Title).AsEnumerable().Skip(1).Take(2);
            //IEnumerable在內存中的 執行腳本,IQueryable和IEnumerable都是延遲執行,tolist的時候在執行
            //SELECT[p].[PostId], [p].[BlogId], [p].[Content], [p].[PersonId], [p].[Title]
            //FROM[Post] AS[p]
            //ORDER BY[p].[Title]

            //foreach (var it in item)
            //{
            //    Console.WriteLine($"it:{it.Title}");
            //} 
            #endregion

            #region 實體跟蹤Tracking
            //一種是全局修改之后在修改回來
            //另外一種是,是使用AsNoTracking()直接修改
            //blogContext.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
            ////using (IDbContextTransaction transaction = blogContext.Database.BeginTransaction())
            ////{
            //var item = blogContext.Post.Where(op => op.Title.Contains("10"));
            ////var item = blogContext.Post.AsNoTracking().Where(op => op.Title.Contains("10"));
            //foreach (var it in item)
            //    {
            //        Console.WriteLine($"it:{it.Title}");
            //        it.Title = "111";
            //    }
            //    blogContext.SaveChanges();
            ////    transaction.Commit();
            ////}
            //blogContext.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.TrackAll;
            #endregion

            #region 模糊查詢StartsWith,,EndsWith,Contains,其中Contains和 EF.Functions.Like功能一樣,但是sql語句翻譯的確實不一樣的
            ////但凡使用的計算函數,索引是一定不會被用上的
            //var item = blogContext.Post.Where(op => op.Title.Contains("10")).ToList();
            ////            SELECT[p].[PostId], [p].[BlogId], [p].[Content], [p].[PersonId], [p].[Title]
            ////            FROM[Post] AS[p]
            ////            WHERE CHARINDEX(N'10', [p].[Title]) > 0
            //foreach (var it in item)
            //{
            //    Console.WriteLine($"it:{it.Title}");
            //}
            //item = blogContext.Post.Where(op => EF.Functions.Like(op.Title, "%10%")).ToList();
            ////            SELECT[p].[PostId], [p].[BlogId], [p].[Content], [p].[PersonId], [p].[Title]
            ////            FROM[Post] AS[p]
            ////            WHERE[p].[Title]
            ////            LIKE N'%10%'
            //foreach (var it in item)
            //{
            //    Console.WriteLine($"it:{it.Title}");
            //}
            #endregion

            #region 自定義標量函數,linq一樣可以翻譯成對應的sql腳本
            ////            SELECT[p].[PostId] AS[id], [dbo].[MyFunction] ([p].[PostId]) AS[name]
            ////FROM[Post] AS[p]
            //var item = blogContext.Post.Select(op => new
            //{
            //    id = op.PostId,
            //    name = BlogContext.MyFunction(op.PostId)//使用標量函數
            //}).ToList();
            //foreach (var it in item)
            //{
            //    Console.WriteLine($"it:{it.name}");
            //}
            #endregion

            #region 編譯查詢

            #region 普通查詢
            //int id = 1;
            //Stopwatch stopwatch = new Stopwatch();
            //stopwatch.Start();
            //var item = blogContext.Post.Where(op => op.PostId == id).FirstOrDefault();
            //stopwatch.Stop();
            //Console.WriteLine($"普通查詢:item:{item.Title},用時:{stopwatch.ElapsedMilliseconds}");
            //            exec sp_executesql N'SELECT TOP(1) [p].[PostId], [p].[BlogId], [p].[Content], [p].[PersonId], [p].[Title]
            //FROM[Post] AS[p]
            //WHERE[p].[PostId] = @__id_0',N'@__id_0 int',@__id_0=1
            #endregion

            #region 編譯查詢
            //Stopwatch stopwatch = new Stopwatch();
            //stopwatch.Start();
            ////var compileQuery = EF.CompileQuery((BlogContext context, int id) => context.Post.Where(c => c.PostId == id).FirstOrDefault());
            ////var item = compileQuery(blogContext, 1);
            //stopwatch.Stop();
            //Console.WriteLine($"普通查詢:item:{item.Title},用時:{stopwatch.ElapsedMilliseconds}");
            #endregion

            //普通查詢

            Func<BlogContext, Blog> unCompileQuery = context => context.Blog.Include(c => c.Posts).Where(a => a.BlogId == 1).FirstOrDefault();
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            Console.WriteLine("普通查詢開始");
            for (int i = 0; i < 100000; i++)
            {
                var a = unCompileQuery(blogContext);
            }
            stopwatch.Stop();
            Console.WriteLine($"編譯查詢 用時:{stopwatch.ElapsedMilliseconds} 毫秒");

            //編譯查詢 一般是大量數據查詢,並且參數不變的情況下比較好,但是不能返回集合
            //Stopwatch stopwatch = new Stopwatch();
            //stopwatch.Start();
            //Console.WriteLine("編譯查詢開始");
            //var compileQuery = EF.CompileQuery((BlogContext context, int id) => context.Blog.Include(c => c.Posts).Where(a => a.BlogId == 1).FirstOrDefault());
            //for (int i = 0; i < 100000; i++)
            //{
            //    var item = compileQuery(blogContext, 1);
            //}
            //stopwatch.Stop();
            //Console.WriteLine($"編譯查詢 用時:{stopwatch.ElapsedMilliseconds} 毫秒");
            #endregion

            //var item = blogContext.Post.Where(op => op.Title.Contains("10"));
            //foreach (var it in item)
            //{
            //    Console.WriteLine($"it:{it.Title}");
            //}
            //var item = blogContext.Post.Where(op => EF.Functions.Like(op.Title,"10"));
            //foreach (var it in item)
            //{
            //    Console.WriteLine($"it:{it.Title}");
            //}

            Console.Read();

        }
    }

    public class BlogContext : DbContext
    {
        public DbSet<Blog> Blog { get; set; }
        public DbSet<Post> Post { get; set; }

        public static readonly ILoggerFactory loggerFactory = LoggerFactory.Create(builder => builder.AddConsole().AddDebug());
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            //optionsBuilder.UseLoggerFactory(loggerFactory);//添加把數據庫操作的信息輸出到指定的控制台
            //optionsBuilder.UseLazyLoadingProxies().UseSqlServer(@"server=127.0.0.1;database=mynetcore;user=sa;password=sa123;");
            //Microsoft.EntityFrameworkCore.SqlServer
            optionsBuilder.UseSqlServer(@"server=127.0.0.1;database=mynetcore;user=sa;password=sa123;");
            //Pomelo.EntityFrameworkCore.MySql
            //optionsBuilder.UseMySql(@"server=127.0.0.1;database=mynetcore;user=root;password=123456;");
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            List<Post> posts = new List<Post>();
            for (int i = 0; i < 20; i++)
            {
                posts.Add(new Post { PostId = i + 1, PersonId = i >= 10 ? 2 : 1, Title = $"文章標題:100{i}", Content = $"文章內容:{i}", BlogId = i >= 10 ? 2 : 1 });
            }
            Blog blogs = new Blog { BlogId = 1, Url = "http://www.baidu.com" };
            Blog blogs1 = new Blog { BlogId = 2, Url = "http://www.tianmao.com" };
            Person person = new Person { PersonId = 1, Name = "123" };
            Person person1 = new Person { PersonId = 2, Name = "456" };
            modelBuilder.Entity<Post>().HasData(posts);
            modelBuilder.Entity<Blog>().HasData(blogs, blogs1);
            modelBuilder.Entity<Person>().HasData(person, person1);
        }

        #region 自定義標量函數
        [DbFunction]
        public static string MyFunction(int id)
        {
            throw new NotImplementedException();
        }
        #endregion
    }
    public class Blog
    {
        public int BlogId { get; set; }
        public string Url { get; set; }
        public virtual List<Post> Posts { get; set; }
    }

    public class Post
    {
        public int PostId { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }
        public int BlogId { get; set; }
        public virtual Blog Blog { get; set; }
        public int PersonId { get; set; }
        public virtual Person Author { get; set; }
    }
    public class Person
    {
        public int PersonId { get; set; }
        public string Name { get; set; }
        public virtual List<Post> Posts { get; set; }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM