5

EFのSaveChangesメソッド/プロセスをオーバーライドする方法を探しています。なんらかの方法でSQLを取得し、通常の更新/削除/挿入が実行されないようにし、生成されたSQLを使用してカスタムプロシージャを実行する必要があります。

  • SaveChanges()通常どおりお電話ください。EFにSQLを生成させます。
  • SQLを取得する
  • そのSQLが通常の方法で実行されないようにする
  • カスタムストアドプロシージャを呼び出します(追加のパラメータなどを取ります)
  • 実行したふりをしますSaveChanges(または単に0を返します)

私が目にする唯一の本当の問題は、SaveChangesメソッド内からSQLを取得することです。私たちがすることは、理想的にはこのようなものです...

  1. プロバイダー/接続/などを取得
  2. これを処理するためのイベントフックを設定します
  3. 完了、コードの変更/オーバーライドなどはありません。

3文字の頭字語のデータベースに対してMVC4とEF5を使用しています。ここでのポイントは、各更新アクションでSQLを手動でコーディングすることを避け、EFに依存してすべてを生成することです。プロシージャはストレートSQLを使用するため

はい、これはそれを行うための良い方法ではありません(単一の手順)が、私たちは問題に選択の余地がありません。何もありません。これができない場合は、カスタムSQLを作成する必要があります。おそらく、これを強制することができる別の方法があります。そこでは、コンテキストを渡し、自分で作業を行いますか?次に、「SaveChanges()」が呼び出されないことを監査できます:D

解決


EFTracingProvider私はこれ(および他のいくつかのこと)を行う独自のプロバイダーを作成するための開始点としてを使用しました。すべてをEntitiesクラスに配置し、イベントを処理することで、EFTracingProviderのみでそれを行うこともできます。このイベントはその後に発生するため、変更されたSQLは表示されないため、独自のロギングを行う必要があります。これは、Webサイトによりよく適合するように削除されました:)

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

2 に答える 2

2

コメントで述べたように、クラッドアクションをストアドプロシージャにマッピングできます(まあ、CUDアクション)。はい、これらのsprocの作成、マッピング、および保守には多くの作業が必要ですが、パフォーマンスとセキュリティが向上する可能性があります。そのため、DBAは彼らをとても気に入っています。データベース内のこの中央のモノリス手順が作成された主な理由でさえあるかもしれません。同じ要件を満たすために「CUDsprocs」を使用する方法があるかもしれません。

于 2012-11-26T21:34:12.887 に答える
2

EF Tracing Providerを使用して SQL を取得することはおそらく可能であるように思われます...このリンクの最後の投稿を参照してください

于 2012-11-26T09:25:08.620 に答える