02020406 EF Core基础06-EF Core生成的SQL
1. 通过代码查看EF Core的SQL语句(视频3-12)
1.1 方法1:标准日志
// 标准日志用法示例
public static readonly ILoggerFactory MyLoggerFactory= LoggerFactory.Create(builder => { builder.AddConsole(); });optionsBuilder.UseLoggerFactory(MyLoggerFactory);
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 需要安装的包
1. microsoft.entityframeworkcore.sqlserver -Version 5.0.4
2. microsoft.entityframeworkcore.tools -Version 5.0.4
3. install-package microsoft.extensions.logging.console -version 5.0.0
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// Dog.cs
namespace DBLogDemo
{public class Dog{public long Id { get; set; }public string Name { get; set; }}
}
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// DbContext.cs
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;namespace DBLogDemo
{class MyDbContext : DbContext{private static ILoggerFactory loggerFactory = LoggerFactory.Create(b => b.AddConsole()); // @1public DbSet<Dog> Dogs { get; set; }protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){string connStr = "Server=.;Database=CoreDataDB;Trusted_Connection=True;MultipleActiveResultSets=true";optionsBuilder.UseSqlServer(connStr);optionsBuilder.UseLoggerFactory(loggerFactory); // @2}protected override void OnModelCreating(ModelBuilder modelBuilder){base.OnModelCreating(modelBuilder);modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);}}
}
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
using System;
using System.Threading.Tasks;namespace DBLogDemo
{class Program{static async Task Main(string[] args){using (MyDbContext ctx = new MyDbContext()){Dog d01 = new Dog();d01.Name = "abc";ctx.Dogs.Add(d01);await ctx.SaveChangesAsync();d01.Name = "abc";Console.WriteLine(d01.Id);}Console.ReadLine();}}
}控制台输出:
info: Microsoft.EntityFrameworkCore.Infrastructure[10403]Entity Framework Core 5.0.4 initialized 'MyDbContext' using provider 'Microsoft.EntityFrameworkCore.SqlServer' with options: None
info: Microsoft.EntityFrameworkCore.Database.Command[20101]Executed DbCommand (31ms) [Parameters=[@p0='?' (Size = 4000)], CommandType='Text', CommandTimeout='30']SET NOCOUNT ON; // 标准SQL语句startINSERT INTO [Dogs] ([Name])VALUES (@p0);SELECT [Id]FROM [Dogs]WHERE @@ROWCOUNT = 1 AND [Id] = scope_identity(); // 标准SQL语句end
2 // Id值
1.2 方法2:简单日志
// 简单日志用法示例
optionsBuilder.LogTo(Console.WriteLine);
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 需要安装的包
1. microsoft.entityframeworkcore.sqlserver -version 5.0.4
2. microsoft.entityframeworkcore.tools -version 5.0.4
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// Dog.cs
namespace DBLogDemo
{public class Dog{public long Id { get; set; }public string Name { get; set; }}
}
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// DbContext.cs
using Microsoft.EntityFrameworkCore;namespace DBLogDemo
{class MyDbContext : DbContext{public DbSet<Dog> Dogs { get; set; }protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){string connStr = "Server=.;Database=CoreDataDB;Trusted_Connection=True;MultipleActiveResultSets=true";optionsBuilder.UseSqlServer(connStr);optionsBuilder.LogTo( msg => {System.Console.WriteLine(msg);}); // LogTo参数为string形式的委托}protected override void OnModelCreating(ModelBuilder modelBuilder){base.OnModelCreating(modelBuilder);modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);}}
}
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// Program.cs
using System;
using System.Threading.Tasks;namespace DBLogDemo
{class Program{static async Task Main(string[] args){using (MyDbContext ctx = new MyDbContext()){Dog d01 = new Dog();d01.Name = "abc";ctx.Dogs.Add(d01);await ctx.SaveChangesAsync();d01.Name = "abc";Console.WriteLine(d01.Id);}Console.ReadLine();}}
}控制台输出:
info: 2025/9/21 20:38:14.997 CoreEventId.ContextInitialized[10403] (Microsoft.EntityFrameworkCore.Infrastructure)
...SaveChanges completed for 'MyDbContext' with 1 entities written to the database.
3 // Id值
dbug: 2025/9/21 20:38:15.510 CoreEventId.ContextDisposed[10407] (Microsoft.EntityFrameworkCore.Infrastructure)'MyDbContext' disposed.说明:
1. 用起来简单,但是看起来好多啊-_-。
2. 可以输出EF Core整个生命周期的日志信息。
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// DbContext.cs
using Microsoft.EntityFrameworkCore;namespace DBLogDemo
{class MyDbContext : DbContext{public DbSet<Dog> Dogs { get; set; }protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){string connStr = "Server=.;Database=CoreDataDB;Trusted_Connection=True;MultipleActiveResultSets=true";optionsBuilder.UseSqlServer(connStr);optionsBuilder.LogTo( msg => { if (!msg.Contains("CommandExecuting")) return; System.Console.WriteLine(msg);}); // 过滤信息,只要SQL语句部分。}protected override void OnModelCreating(ModelBuilder modelBuilder){base.OnModelCreating(modelBuilder);modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);}}
}
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// Program.csusing System;
using System.Threading.Tasks;namespace DBLogDemo
{class Program{static async Task Main(string[] args){using (MyDbContext ctx = new MyDbContext()){Dog d01 = new Dog();d01.Name = "abc";ctx.Dogs.Add(d01);await ctx.SaveChangesAsync();d01.Name = "abc";Console.WriteLine(d01.Id);}Console.ReadLine();}}
}控制台输出:
dbug: 2025/9/21 20:46:21.950 RelationalEventId.CommandExecuting[20100] (Microsoft.EntityFrameworkCore.Database.Command)Executing DbCommand [Parameters=[@p0='?' (Size = 4000)], CommandType='Text', CommandTimeout='30']SET NOCOUNT ON;INSERT INTO [Dogs] ([Name])VALUES (@p0);SELECT [Id]FROM [Dogs]WHERE @@ROWCOUNT = 1 AND [Id] = scope_identity();
5说明:只输出SQL语句部分。
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// Program.cs,演示多条SQL语句。
using System;
using System.Linq;
using System.Threading.Tasks;namespace DBLogDemo
{class Program{static async Task Main(string[] args){using (MyDbContext ctx = new MyDbContext()){Dog d01 = new Dog();d01.Name = "abc";ctx.Dogs.Add(d01); // SQL语句1ctx.Dogs.Add(new Dog { Name = "Trump" }); // SQL语句2await ctx.SaveChangesAsync();Console.WriteLine(ctx.Dogs.Count()); // SQL语句3}Console.ReadLine();}}
}控制台输出:
dbug: 2025/9/21 20:52:51.558 RelationalEventId.CommandExecuting[20100] (Microsoft.EntityFrameworkCore.Database.Command)Executing DbCommand [Parameters=[@p0='?' (Size = 4000)], CommandType='Text', CommandTimeout='30']SET NOCOUNT ON;INSERT INTO [Dogs] ([Name])VALUES (@p0);SELECT [Id]FROM [Dogs]WHERE @@ROWCOUNT = 1 AND [Id] = scope_identity();
dbug: 2025/9/21 20:52:51.624 RelationalEventId.CommandExecuting[20100] (Microsoft.EntityFrameworkCore.Database.Command)Executing DbCommand [Parameters=[@p0='?' (Size = 4000)], CommandType='Text', CommandTimeout='30']SET NOCOUNT ON;INSERT INTO [Dogs] ([Name])VALUES (@p0);SELECT [Id]FROM [Dogs]WHERE @@ROWCOUNT = 1 AND [Id] = scope_identity();
dbug: 2025/9/21 20:52:51.854 RelationalEventId.CommandExecuting[20100] (Microsoft.EntityFrameworkCore.Database.Command)Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']SELECT COUNT(*)FROM [Dogs] AS [d]说明:过滤后每个SQL操作的语句都可以查到,如果SQL操作很多,那么输出很多个SQL语句,查起来会很麻烦。可以定向的找到所需要的SQL语句。
1.3 方法3:ToQueryString
1、上面两种方式无法直接得到一个操作的SQL语句,而且在操作很多的情况下,容易混乱。
2、EF Core的Where方法返回的是IQueryable类型,DbSet也实现了IQueryable接口。 IQueryable有扩展方法ToQueryString()可以获得SQL。
3、不需要真的执行查询才获取SQL语句;只能获取查询操作的。
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// Dog.cs
namespace DBLogDemo
{public class Dog{public long Id { get; set; } //主键public string Name { get; set; }//标题}
}
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// MyDbContext
using Microsoft.EntityFrameworkCore;namespace DBLogDemo
{class MyDbContext : DbContext{public DbSet<Dog> Dogs { get; set; }protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){string connStr = "Server=.;Database=CoreDataDB;Trusted_Connection=True;MultipleActiveResultSets=true";optionsBuilder.UseSqlServer(connStr);}protected override void OnModelCreating(ModelBuilder modelBuilder){base.OnModelCreating(modelBuilder);modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);}}
}
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Threading.Tasks;namespace DBLogDemo
{class Program{static async Task Main(string[] args){using (MyDbContext ctx = new MyDbContext()){Dog d01 = new Dog();d01.Name = "abc";ctx.Dogs.Add(d01);ctx.Dogs.Add(new Dog { Name = "Trump" }); // 拿不到await ctx.SaveChangesAsync();Console.WriteLine(ctx.Dogs.Count()); // 拿不到IQueryable<Dog> dogs01 = ctx.Dogs.Where(d => d.Name.ToLower() == "Trump");string sql = dogs01.ToQueryString();Console.WriteLine("这就是我要的SQL语句:" + sql); // ToQueryStirng只能拿到查询操作的SQL语句/*foreach (var it in d02){Console.WriteLine(it.Id);}*/}Console.ReadLine();}}
}控制台输出:
13
SELECT [d].[Id], [d].[Name]
FROM [Dogs] AS [d]
WHERE LOWER([d].[Name]) = N'Trump'说明:
1. ToQueryString方法只能拿到查询操作的SQL语句,其它形式的SQL语句拿不到。
2. ToQueryString方法可以在不真的执行数据库查询的情形下直接拿到查询结果,后续课程会演示。
1.4 总结
- 写测试性代码,用简单日志;
- 正式需要记录SQL给审核人员或者排查故障,用标准日志;
- 开发阶段,从繁杂的查询操作中立即看到SQL,用ToQueryString()。
2. 同样的LINQ被翻译为不同的SQL语句(视频3-13)
- 本课跳过,目前只针对性的学习SQL Server。本机也没安装其它数据库,无法演示。
- 后续用得到再补。
结尾
书籍:ASP.NET Core技术内幕与项目实战
视频:https://www.bilibili.com/video/BV1pK41137He
著:杨中科
ISBN:978-7-115-58657-5
版次:第1版
发行:人民邮电出版社
※敬请购买正版书籍,侵删请联系85863947@qq.com※
※本文章为看书或查阅资料而总结的笔记,仅供参考,如有错误请留言指正,谢谢!※