覆盖EntityFramework SaveChanges - 获取SQL并调用自定义proc

And*_*ker 5 c# entity-framework entity-framework-5

我正在寻找一种方法来覆盖EF中的SaveChanges方法/过程.我们需要以某种方式获取SQL,阻止正常的更新/删除/插入执行,并使用生成的SQL来运行我们的自定义过程.

  • SaveChanges()正常打电话.让EF生成SQL.
  • 获取SQL
  • 防止SQL以正常方式执行
  • 调用自定义存储过程(需要额外的参数等)
  • 假装我们执行SaveChanges(或只返回0)

我看到的唯一真正的问题是从SaveChanges方法内部抓取SQL .我们要做的就是这样,理想情况......

  1. 获取提供者/连接/等
  2. 设置事件挂钩来处理这个问题
  3. 完成,没有代码更改/覆盖等.

我们使用MVC4和EF5来对抗3个字母的首字母缩略词数据库.这里的要点是避免在每个更新操作中手动编写SQL,并依靠EF为我们生成所有这些.由于该过程采用直接SQL

是的,这不是一个好方法(单一程序),但我们别无选择.没有任何.如果我们不能这样做,那么我们将需要编写自定义sql.也许我们可以采用另一种方式来实现这一点,我们可以通过上下文并自己完成工作?然后我们可以审核从未调用'SaveChanges()':D


我用它EFTracingProvider作为起点来创建我自己的提供者(以及其他一些东西).您也可以通过将所有内容放在Entities类中并处理事件来使用EFTracingProvider.您将看不到修改后的SQL,因为此事件将在此之后触发,因此您需要自己进行日志记录.这已被剥离,以更好地适应网站:)

public class MyEntities : MyBaseEntities
{

    public MyEntities(): this(connectionString: "name=MyBaseEntities") {}
    public MyEntities(string connectionString) 
             : base(MakeConnection(connectionString, "EFTracingProvider")) {}

    /// <summary>
    /// Insert the wrapped connection by calling the base toolkit.
    private static EntityConnection MakeConnection(string connectionString, params string[] providers)
    {
        var conn = EntityConnectionWrapperUtils.CreateEntityConnectionWithWrappers(
            connectionString,
            providers
            );

        //get the tracing connection, so that we can attach event handlers
        var us = conn.UnwrapConnection<EFTracingConnection>();
        if (us != null)
        {
            us.CommandExecuting += BeforeExecute;
        }
        return conn;
    }

    private static void BeforeExecute(object sender, CommandExecutionEventArgs e)
    {
        // If an Create/Update/Delete action then we need to wrap it in our custom proc   
        if (IsCudAction(e.CommandTree))
        {
            var text = cmd.Parameters.Cast<DbParameter>().Aggregate(
                cmd.CommandText, 
                (current, p) => current.Replace(p.ParameterName, SafeSql.Prepare(p.Value)));

            cmd.CommandType = CommandType.StoredProcedure;
            cmd.CommandText = "[dbo].[ExecuteForMe]";
            cmd.Parameters.Clear();
            cmd.Parameters.AddRange(new[]
                {
                    new SqlParameter("commandText", text),
                    new SqlParameter("extraInfo", "logging context")
                });
        }
    }

    public static bool IsCudAction(DbCommandTree commandTree)
    {
        if (commandTree is DbUpdateCommandTree) return true;
        if (commandTree is DbDeleteCommandTree) return true;
        if (commandTree is DbInsertCommandTree) return true;
        if (commandTree is DbQueryCommandTree) return false;
        if (commandTree is DbFunctionCommandTree) return false;
        throw new InvalidOperationException("Unknown type of CommandTree: " + commandTree.GetType().Name);
    }
}
Run Code Online (Sandbox Code Playgroud)

Pau*_*hra 2

似乎可以使用EF Tracing Provider获取 SQL ...请参阅此链接中的最后一篇文章