一、使用日志记录
1.1 标准日志
1.1.1 静态日志工厂
1. 定义静态日志工厂:在MyDbContext类中直接定义一个静态只读的ILoggerFactory字段,并使用 LoggerFactory.Create方法进行初始化。
public static readonly ILoggerFactory loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddConsole(); // 输出到控制台
});
2.在 OnConfiguring 方法中使用日志工厂:在 OnConfiguring方法中调用 UseLoggerFactory方法,将日志工厂传递给 EF Core。
optionsBuilder.UseLoggerFactory(loggerFactory);
1.1.2 依赖注入实现日志工厂
确保 MyDbContext 接受 ILoggerFactory 作为构造函数的参数,并在 OnConfiguring 方法中使用它进行日志配置。
public class MyDbContext : DbContext
{
// 使用代码查看Sql语句,标准日志
// 1. 依赖注入实现日志工厂
public readonly ILoggerFactory _loggerFactory;
public MyDbContext(ILoggerFactory loggerFactory)
{
_loggerFactory = loggerFactory;
}
/// <summary>
/// 配置数据库连接。
/// </summary>
/// <param name="optionsBuilder"></param>
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
// 1. 定义数据库连接字符串
String connectionString = "";
// 2. 指定数据库类型为 MySQL
optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
// 3. 配置日志
optionsBuilder.UseLoggerFactory(_loggerFactory);
}
}
使用 ServiceCollection 来配置日志记录服务,并将其传递给 MyDbContext。
private static void Main(string[] args)
{
// 1. 创建服务集合
ServiceCollection services = new();
// 2. 添加日志服务
services.AddLogging(logger => logger.AddConsole());
// 3.构建服务提供者
ServiceProvider sp = services.BuildServiceProvider();
// 4. 获取日志工厂
var logger = sp.GetService<ILoggerFactory>();
// 5. 创建数据库上下文实例并传入日志工厂
using (MyDbContext myDb = new(logger))
{
AddData(myDb);
}
}
private static void AddData(MyDbContext myDb)
{
// 1. 创建的数据库上下文实例
Book book = new Book
{
Title = "C#入门",
PubTime = DateTime.Now,
Price = 99.99,
AuthorName = "张三"
};
// 2. 将新创建的 Book 对象添加到 Books 集合中(逻辑上的添加)
myDb.Books.Add(book);
// 3. 提交更改,将数据保存到数据库中(实际的添加)
myDb.SaveChanges();
}
1.2 简单日志
在数据库上下文的 OnConfiguring 方法中加入以下内容
optionsBuilder.LogTo(Console.WriteLine, LogLevel.Information);
二、ToQueryString()
- 查询操作:通过 LINQ 表达式构建查询,并可以通过 ToQueryString() 方法查看生成的 SQL 查询语句。
- 插入、更新或删除操作:不能使用 ToQueryString() 直接获取生成的 SQL 语句,但可以通过配置日志记录服务查询操作。
private static void Main(string[] args)
{
using (MyDbContext myDb = new())
{
IQueryable<Book> result = myDb.Books.Where(b => b.Title == "C#入门");
string sql = result.ToQueryString();
Console.WriteLine(sql);
}
}
IQueryable<Book> result = myDb.Books.Where(b => b.Title == "C#入门"); 这行代码并没有立即执行数据库查询。这是因为EF采用了延迟加载的机制。
具体来说,当你编写如myDb.Books.Where(b => b.Title == "C#入门")这样的LINQ查询时,EF并不会立刻去数据库执行这个查询。相反,它会构建一个表达式树(Expression Tree),这个表达式树描述了你想要执行的操作。只有当你进一步操作这个查询结果,比如调用 ToList()、FirstOrDefault() 等方法时,EF才会将这个表达式树转换为SQL语句,并发送到数据库执行。
总结:
- myDb.Books.Where(b => b.Title == "C#入门") 构建了一个表达式树,描述了你想要执行的查询。
- ToQueryString() 方法用于获取这个表达式树对应的SQL语句字符串。
- 实际的数据库查询会在你尝试获取查询结果(如 ToList()、FirstOrDefault() 等)时才被执行。