7

私はEntity Framework 5とSQL Server 2008と共にVisual Studio 2012を使用してデータベースアプリケーションを作成しています。Entity FrameworkでSQL Serverユーザー(つまり、ログイン)。 DBコンテキストMyDatabaseEntities用の新しいコンストラクタを作成しました。このコンストラクタには、偽装するユーザーの名前の引数が含まれています。方法Connection_StateChange方法は、状態が「hasn場合でも実行するようなのでEntity Framework 5 - SQL Serverの "ユーザーとして実行"

public partial class MyDatabaseEntities 
{ 
    private String _impersonateUser = null; 

    public MyDatabaseEntities(String impersonateUser) 
     : base("MyConnectionString") 
    { 
     _impersonateUser = impersonateUser; 

     this.Database.Connection.StateChange += Connection_StateChange; 

    } 

    void Connection_StateChange(object sender, StateChangeEventArgs e) 
    { 
     if (e.CurrentState == ConnectionState.Open && e.OriginalState != ConnectionState.Open) 
     { 
      using (var cmd = this.Database.Connection.CreateCommand()) 
      { 
       cmd.CommandType = CommandType.Text; 

       cmd.Parameters.Add(new SqlParameter("user", _impersonateUser)); 

       cmd.CommandText = "EXECUTE AS USER = @user"; 

       cmd.ExecuteNonQuery(); 

      } 

     } 

    } 

私はチェックを追加する必要がありました...

if (e.CurrentState == ConnectionState.Open && e.OriginalState != ConnectionState.Open) 

...:ここで私が書いたコードですtは変わった。そして、問題は、私は、コード二回

public void RunSimpleQuery() 
{ 
    using (MyDatabaseEntities context = new MyDatabaseEntities("UserName")) 
    { 
     var result = context.TableName.ToList(); 

    } 

} 

を実行したときに... Entity FrameworkのはSqlExceptionを投げることです:

重大なエラーが現在のコマンドでが発生しました。結果が の場合は破棄してください。\ 012 \ n現在の コマンドで重大なエラーが発生しました。もしあれば、結果は破棄されるべきです。

Update 1の私は上記の私のコードでは、私が変更

...

cmd.CommandText = "EXECUTE AS USER = @user;"; 

...へ...

cmd.CommandText = "REVERT; EXECUTE AS USER = @user;"; 

...と私はまだ同じSqlExceptionエラーが発生します。

+0

問題は、EFが接続を必要としないときに接続を閉じてプールに戻すことです。したがって、SQLを再度実行すると、イベントが初期化されないプールから新しい接続を要求します。 –

+0

@LadislavMrnkaはい、問題を特定しました。私は接続文字列で接続プールを使わないように指定しなければならないと思う...それは残念だ。私はあなたに信用を与えることができるので、これのための答えを作成してください(あなたがコメントで言ったことを言う)。ありがとう! – HydroPowerDeveloper

+0

あなたは接続を自分自身で(DbContextに渡すことによって)制御しようとするべきですが、これにはいくつかの問題がありました:http://blogs.msdn.com/b/diego/archive/2012/01/26/exception -from-dbcontext-api-entity-connection-can-only-be-closed-with-dbconnection.aspxで作成できます。 –

答えて

6

問題は、EFが接続を必要としないときに接続を閉じてプールに戻すことです。したがって、SQLを再度実行すると、イベントが初期化されないプールから新しい接続を要求します。しかし、もう一度、接続プールの利点と要件を満たすことができるように、接続ライフタイムを手動で制御することでこれを解決しようとするべきだと考えています。

+0

ご協力いただきありがとうございます。 – HydroPowerDeveloper

+0

BTW:接続ライフタイムを手動で制御して偽装接続プーリングのメリットを得ることについてアドバイスをしています(提供したリンクが非常に役立ちます)。私はあなたの道を行くつもりだと思う。私は自分のコードを更新して別のアップデートとして投稿します。 – HydroPowerDeveloper

1

私は古い質問があることを知っていますが、おそらく誰かにとって役に立ちます。私はあなたのコードを使用して、別の方法で行った

...

代わりの

Connection_StateChangedイベント

私は同じクラスに2つのメソッドを作成:

public void ChangeUser(String sUser) 
    { 
     if(Database.Connection.State != ConnectionState.Open) 
      Database.Connection.Open(); 

     using (var cmd = Database.Connection.CreateCommand()) 
     { 
      cmd.CommandType = CommandType.Text; 
      cmd.Parameters.Add(new SqlParameter("user", sUser)); 
      cmd.CommandText = "EXECUTE AS USER = @user;"; 
      cmd.ExecuteNonQuery(); 
     } 
    } 

    public void Revert() 
    { 
     if (Database.Connection.State != ConnectionState.Open) 
      Database.Connection.Open(); 

     using (var cmd = Database.Connection.CreateCommand()) 
     { 
      cmd.CommandType = CommandType.Text; 
      cmd.CommandText = "REVERT;"; 
      cmd.ExecuteNonQuery(); 
     } 
    } 

ストアドプロシージャの実行前後で使用します。

using (var db = new MyDatabaseEntities()) 
     { 
      db.ChangeUser(model.Username); 
      var result = db.Something(); 
      db.Revert(); 
      return result; 
     } 

これはSPで正常に動作し、多くの実行後も例外をスローしません。コマンド実行後にイベントを捕まえることができたら、おそらくすべてMyDatabaseEntitiesにカプセル化されます。

関連する問題