2016-10-22 10 views
1

学習の練習として、ORM(EFなど)を使用する前に、ADO.NETとストアドプロシージャを使用して個人用プロジェクトを作成したいと考えています。SQL Server:トランザクションでSELECTクエリをラップすると、パフォーマンス上のペナルティはありますか?

時間が経つにつれて自分のコードが混乱したくないので、リポジトリやUoWパターンのようなパターンを使いたいと思っています。

トランザクションの処理を除いて、ほとんどすべてがわかりました。

どういうわけか 'UWでシミュレート'するには、@ jgauffinによって提供されたthis classを使用しましたが、そのクラスの使用を止めるのは、そのクラスの新しいインスタンス(AdoNetUnitOfWork)を作成するたびに、あなたがデータを読む必要があるだけの多くのケースがあります。ターンブロックに、参照されるテーブルのロックを作成することができ、トランザクション内でSELECT文を実行

これがすることができます。このこの点で

は、私はSQLの本私が読んでいるのいずれかで見つけたものです他のユーザーやセッションデータを作業を行うか、読んでから

これはAdoNetUnitOfWorkクラスです:

public class AdoNetUnitOfWork : IUnitOfWork 
{ 
    public AdoNetUnitOfWork(IDbConnection connection, bool ownsConnection) 
    { 
     _connection = connection; 
     _ownsConnection=ownsConnection; 
     _transaction = connection.BeginTransaction(); 
    } 

    public IDbCommand CreateCommand() 
    { 
     var command = _connection.CreateCommand(); 
     command.Transaction = _transaction; 
     return command; 
    } 

    public void SaveChanges() 
    { 
     if (_transaction == null) 
      throw new InvalidOperationException("Transaction have already been commited. Check your transaction handling."); 

     _transaction.Commit(); 
     _transaction = null; 
    } 

    public void Dispose() 
    { 
     if (_transaction != null) 
     { 
      _transaction.Rollback(); 
      _transaction = null; 
     } 

     if (_connection != null && _ownsConnection) 
     { 
      _connection.Close(); 
      _connection = null; 
     } 
    } 
} 

そして、これは私が私のリポジトリにUOWを使用する方法である:私はトランザクションはオプションになるように、私はこのコードを少し微調整することができます知っている

public DomainTable Get(int id) 
{ 
    DomainTable table; 

    using (var commandTable = _unitOfWork.CreateCommand()) 
    { 
     commandTable.CommandType = CommandType.StoredProcedure; 
     //This stored procedure contains just a simple SELECT statement 
     commandTable.CommandText = "up_DomainTable_GetById"; 

     commandTable.Parameters.Add(commandTable.CreateParameter("@pId", id)); 

     table = ToList(commandTable).FirstOrDefault(); 
    } 

    return table; 
} 

が、私は可能な独立したプラットフォームとして、このコードをしようとしているので私がEFのような他の永続性フレームワークで知っている限り、トランザクションを手動で管理する必要はありません。問題は、このクラスをそのまま使用して、つまりトランザクションが常に作成されることで何らかのボトルネックが発生するかどうかです?

+1

http://dba.stackexchange.com/questions/43254/is-it-a-bad-practice-to-always-create-a-transaction https://social.msdn.microsoft.com/Forums/ sqlserver/en-US/18a09050-79a8-4c83-99e6-1335a14604e0/why-wrap-just-a-select-in-a-transaction?forum = transactsql –

答えて

6

これはすべてtransaction isolation levelに依存します。デフォルトの独立性レベル(すなわち、読み取りコミット)を使用すると、SELECTは、トランザクションでラップされても、パフォーマンス上のペナルティは発生しません。 SQL Serverは、トランザクションが開始されていない場合は、トランザクション内のステートメントを内部的にラップするため、コードはほとんど同じ動作をします。

しかし、私はあなたに組み込みの.Net TransactionScopeを使わないように頼む必要がありますか? TransactionScopeが普遍的に使用されているので、このようにしてコードは他のライブラリやフレームワークとの相互作用をより良くします。これに切り替える場合は、デフォルトでTransactionScopeがSERIALIZABLE分離レベルを使用しており、これによりパフォーマンスが低下することを警告しなければなりません。using new TransactionScope() Considered Harmfulを参照してください。

+0

ありがとうございます@残念です。私は他の質問でも言及されていますが、**デフォルトで** SQLは内部的にすべてのステートメントのトランザクションを作成しますが、私はそれを確認するソースを見つけることができませんでした。あなたがなぜ「TransactionScope」を使っていないのかと疑問に思っています。少し時間がたっても、データベースとC#について読んできたのは初めてです。(私はフロントエンドの開発者ですバックエンドの世界に入るために)、それは興味深いように聞こえる。 – eddy

+0

私はすべてのプロジェクトが異なっていますが、あなたの経験に基づいて、あなたに最も有用であると判明した分離レベルのタイプや、新しいプロジェクトを開始するたびにいつもデフォルトになるタイプの分離レベルを知っていますか? – eddy

+0

私はそれを変更する特別な理由がない限り、コミットされたままにしておきます。 –

関連する問題