怎么看EF SaveChanges()生成什么sql

时间:2016-11-04 12:43:12

标签: c# entity-framework

我很想知道EF SaveChanges()生成了什么sql。所以我搜索谷歌并发现了一个简单的技巧。

我创建了类

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

也以这种方式挂钩日志功能

    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()函数生成的插入或更新语句的正确值。

1 个答案:

答案 0 :(得分:0)

幸运的是,几年前我不得不做类似的事情。您要做的是创建一个从DatabaseLogFormatter派生的新类,重写NonQueryExecuted方法并使用DbCommand参数。此对象将在CommandText属性中保存SQL命令generate,并在Parameters中保存其值的参数。当然,您必须执行命令文本和参数,并创建一个新的sql命令字符串,它看起来像一个ordinaly 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。您必须向DbContex命名空间添加一个新类

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

何时使用

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

命令字符串格式正确。

希望这有帮助。

实施不是那么好,所以你应该很容易做到。但由于我是Stackoverflow的新手,我将举例说明已实现的方法。 ReplaceWholeWord函数取自Way to have String.Replace only hit "whole words"

 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));
    }

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