如何查看EF SaveChanges()生成什么sql

本文关键字:什么 sql 何查看 EF SaveChanges | 更新日期: 2023-09-27 18:16:40

我很想看看EF SaveChanges()生成了什么sql。于是我在谷歌上搜索了一下,找到了一个简单的方法。

我创建了类
public class MyLogger
{
    public static void Log(string component, string message)
    {
        Console.WriteLine("Component: {0} Message: {1} ", component, message);
    }
}

也可以用这种方式hook log函数

    using (var db = new TestDBContext())
    {
        db.Database.Log = s => MyLogger.Log("EFApp", s);
var existingCustomer = db.Customer
.Include(a => a.Addresses.Select(x => x.Contacts))
.FirstOrDefault(p => p.CustomerID == 5);
        existingCustomer.FirstName = "Test Customer123";
        db.SaveChanges();
    }  

,看到生成的部分插入SQL语句如下

INSERT [dbo].[Addresses]([Address1], [Address2], [IsDefault], [SerialNo], [CustomerID])
VALUES (@0, @1, @2, @3, @4)
SELECT [AddressID]
FROM [dbo].[Addresses]
WHERE @@ROWCOUNT > 0 AND [AddressID] = scope_identity()

为什么我说偏部分,因为没有值。所以请告诉我如何看到SaveChanges()函数生成的正确值的插入或更新语句。

如何查看EF SaveChanges()生成什么sql

幸运的是,几年前我不得不做类似的事情。你要做的是创建一个从DatabaseLogFormatter派生的新类,覆盖nonqueryperformed方法并使用DbCommand参数。该对象将保存CommandText属性中生成的SQL命令和parameters中的参数及其值。当然,您必须处理命令文本和参数,并创建一个看起来像普通sql语句的新sql命令字符串。

class EFCustomLogFormatter:: DatabaseLogFormatter
{ 
    public EFCustomLogFormatter(DbContext context, Action<string>  writeAction): base(context, writeAction)
    {
    }
    public override void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
    {
       //process your command and text
       Write(processedCommand);
    }
 }

完成上述所有操作后,需要将新的日志记录器连接到DbContext。必须向dbcontext名称空间添加一个新类

 public class NewLoggerForEF: DbConfiguration
    {
        public NewLoggerForEF()
        {
            SetDatabaseLogFormatter((context, writeAction) => new   EFCustomLogFormatter(context, writeAction));
        }
    }

何时使用

db.Database.Log = command => MyLogger.Log("EFApp", command)

命令字符串将被正确格式化。

希望对你有帮助。

实现不是那么困难,所以你应该很容易做到。但是由于我是Stackoverflow的新手,我将给你一个实现方法的例子。ReplaceWholeWord函数取自Way,取自have String。替换只命中"整字"

 public override void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
    {
        foreach (DbParameter parameter in command.Parameters)
        {
            command.CommandText = StringExtendsionsMethods.ReplaceWholeWord(command.CommandText, parametru.ParameterName, "'" + parametru.Value.ToString() + "'");
        }

        string filterR = command.CommandText.Replace(''r', ' ');
        string filterN = faraR.Replace(''n', ' ');
        string cleanSQLCommand = filterN.Replace('`', ' ');

        Write(string.Format(cleanSQLCommand));
    }

同样,它可能需要一些调整,所以要彻底测试。