02020406 EF Core基础06-EF Core生成的SQL
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()); // @1
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.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语句start
INSERT 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.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();
}
}
}
控制台输出:
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语句1
ctx.Dogs.Add(new Dog { Name = "Trump" }); // SQL语句2
await 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※
※本文章为看书或查阅资料而总结的笔记,仅供参考,如有错误请留言指正,谢谢!※