1

UnitOfWorkパターンについて過去2日間読んでいますが、正しく理解できませんでした。

クラスごとにリポジトリがあります。例えば。従業員、出席、給与、部門、住所など。

リポジトリとは-これらの各クラスには独自のCRUD操作があります(独自のデータベース接続を作成します)。これらは個別のデータベース接続を作成し、挿入します。

複数の操作をアトミックとして実行したい場合に問題が発生します。例えば。単一のトランザクションで従業員と住所に挿入します。しかし、従業員は従業員テーブルのみを管理する責任があるため、私のリポジトリでは許可されていません。

System.Transactionsを使用できますが、1つのトランザクションに多数のデータベース接続があるため、これは私を夢中にさせます。

UoWは私の場合に適用されますが、いくつかの変更を加えますか?

編集:

私のサンプルコード

public class AccountTransactionManager
{
    Properties.Settings settings = new Properties.Settings();

    public void InsertAccountTransaction(AccountTransaction accountTransaction)
    {
        SqlParameter AccountId = new SqlParameter { ParameterName = "@AccountId", Value = accountTransaction.AccountId, Direction = ParameterDirection.Input, SqlDbType = SqlDbType.Int };
        SqlParameter PAYMENT_DATE = new SqlParameter { ParameterName = "@PAYMENT_DATE", Value = accountTransaction.PAYMENT_DATE, Direction = ParameterDirection.Input, SqlDbType = SqlDbType.DateTime };
        SqlParameter CURRENT_BALANCE = new SqlParameter { ParameterName = "@CURRENT_BALANCE", Value = accountTransaction.CURRENT_BALANCE, Direction = ParameterDirection.Input, SqlDbType = SqlDbType.Money };

        Helper.SqlHelper.Execute(settings.SQLConnectStr
            , (tran) =>
            {
                Helper.SqlHelper.ExecuteNonQuery(tran, CommandType.StoredProcedure, "usp_AccountTransactionInsert", AccountId, PAYMENT_DATE, CURRENT_BALANCE);
            });
    }
}

SqlHelperコード

public static void Execute(string connectionString, Action<SqlTransaction> CallBack)
{
    if (CallBack == null)
        return;

    using (var con = new SqlConnection(connectionString))
    {
        con.Open();
        using (var tran = con.BeginTransaction())
        {
            #region Call procedures

            try
            {
                CallBack(tran);
                tran.Commit();
            }
            catch (SqlException ex)
            {
                tran.Rollback();
                throw ex;
            }
            finally
            {
                con.Close();
            }

            #endregion
        }
    }
}

要件は非常に頻繁に変更されます。したがって、ORMを使用するか、独自のリポジトリを作成する必要があります。ORMでストアドプロシージャを使用できますか?

4

2 に答える 2

2

あなたはそこにいくつかの非常に間違った仮定を持っています。まず、リポジトリが2つあるからといって、両方を使用してもデータベース接続が2つあるわけではありません。データベース接続は、EntityFrameworkやnHibernateなどのほとんどのORMによってプールされます。したがって、接続がどのように処理されるかはわかりませんが、SaveChangesを呼び出すと、暗黙のトランザクションが発生し、単一のアトミックアクションとして発生することが一般的に保証されます。

次に、ORMの主な利点の1つである、ナビゲーションプロパティとコレクションを無視しています。Employeeテーブルがある場合は、AddressナビゲーションプロパティまたはCollectionofAddressesが必要です。

したがって、新しい従業員を挿入するとします。新しい従業員エンティティを作成してから、新しい住所エンティティを作成し、住所を従業員に追加してから、従業員をORMに追加します。CommitやSaveChangesなどを呼び出すと、ORMが更新され、両方のエンティティが更新され、単一のトランザクションとして実行されます。

同様に、複数の従業員を追加する場合、SaveChangesを呼び出すと、それらすべてが1つのトランザクションとして追加されます。

分散トランザクションが必要になる可能性があると思われる場合にのみ、System.Transactionを使用する必要があります。または、単一の作業単位では実行できない複数のステップのプロセスが本当にあります。

あなたが話していることの多くは、各リポジトリがそれ自身の独立した作業単位であるという仮定に基づいており、それはまったく必要な仮定ではありません。UnitOfWorksは、すべてのリポジトリ間で共有できます。依存性注入を使用している場合、これはさらに簡単に実行できます。

編集:

あなたの編集に基づいて、あなたはORMを使用しておらず、むしろリポジトリを使用してDALを処理しているようです。私が言ったことのいくつかはまだ当てはまります。エンティティには管理可能な関連エンティティがあるため、各リポジトリに独自の接続を設定する必要はなく、単一のエンティティのみを処理するリポジトリを作成する必要もありません。

UnitOfWorkについて覚えておくべき重要なことは、それが一種のエンティティキャッシュであるということです。ダーティエンティティを追加または更新すると、それらが1つずつ保存されることはありません...代わりに、Saveを呼び出すまで待機し、その後、すべてを1つのトランザクションで実行します。

さらに、リポジトリは作業単位ではなく、UnitOfWorkのラッパーです。UnitOfWorkは、単一のエンティティだけでなく、モデル内のすべてのエンティティを追跡します。したがって、複数のリポジトリが単一のUnitOfWorkを共有できます。

于 2012-09-13T05:25:58.040 に答える
1

UnitOfWorkパターンは、Modelオブジェクトの状態と、それをデータベースに保存する必要があるかどうかを管理するために使用されます。

モデルオブジェクトのプロパティを変更すると、オブジェクトは変更されたことを認識し(通常はダーティとしてマークされます)、このオブジェクトは永続化メカニズムによって処理されます。IListに10個のオブジェクトがある場合があります(そのうちの2つを変更します)。永続層を保存するときは、2つだけが変更されたことを認識し、それらのみをデータベースに保存します。

これがどのように機能するかについて詳しくは、こちらをご覧ください。

物事の音によって、あなたが抱えている本当の問題は、永続層(リポジトリ)をどのように作成するかです。必要なのは、データベースへの接続を保持するが、アセンブリ内のすべてのリポジトリからアクセスできる方法で接続を保持する、何らかの形式の単一接続管理オブジェクトです。必要なのは、おそらく静的ファクトリパターンを使用して作成されたシングルトンオブジェクトです。

正直なところ、これはかなり低レベルのデータアクセスコードであり、トランザクション(コミット済み、トランザクション中など)と接続状態(オープン、クローズ)の管理は厄介なコードになる可能性があります。最近では、nHibernate、Entity Framework、Active Recordなど、これらすべてのことを実行するフレームワークがいくつかあります(皮肉なことに、説明するパターンの多くを使用しています)。

編集:あなたのコードを見ただけです。本当に本当に自分でやりたい場合は、SQLHelperクラスからstaticキーワードを削除し、接続コードをopenとcloseという別のメソッドに移動して、SQLHelperクラスを常に単一のインスタンスを返す新しい静的ファクトリクラスにラップします(シングルトン)。

于 2012-09-13T05:31:28.350 に答える