0

UnitDataProvider クラスの 2 つのメソッドを呼び出している unitservice でこの疑似コードを実行しています。

var units = dataProvider.GetChildrenUnits(parentId);
unit.HierarchyIndex = units.Where( u => u.TemplateId == unit.TemplateId && u.ParentId == null).Max( u => u.HierarchyIndex) + 1;
dataProvider.AddSiblingUnit(unit);

すべてのメソッドが接続を開きます。

これをどのようにリファクタリングして、1 つの接続のみを使用するか、開いている接続を再利用できますか?

それとも、データプロバイダーのメソッド呼び出しごとに接続するのが普通だと思いますか?

解決策: データベース上のすべてのデータ アクセス ロジックは、BLL ではなく DAL 内で実行されます。

public void AddSiblingUnit(Unit unit) 
        {
            if (unit.ParentId == null)
            {
                throw new OnlyOneRootNodeIsAllowedException("Only one Root node is allowed!", null);
            } // Server side check if the root is selected because 2 root units are not allowed

            lock (_lockObject)
            {
                using (var trans = new TransactionScope())
                using (var con = new SqlConnection(_connectionString))
                using (var cmd = new SqlCommand())
                {
                    cmd.Connection = con;
                    con.Open();

                    // SELECT HierarchyIndex for the new inserted sibling
                    string selectCommandText = "SELECT HierarchyIndex FROM UNIT WHERE UnitId = @UnitId"; // UnitId of the selected sibling
                    cmd.CommandText = selectCommandText;
                    cmd.Parameters.AddWithValue("UnitId", unit.UnitId); // the parentId which is the selected UnitId 
                    int hierarchyIndexOfSelectedSibling = Convert.ToInt32(cmd.ExecuteScalar());
                    int hierarchyIndexOfNewSibling = hierarchyIndexOfSelectedSibling + 1;

                    // UPDATE all sibling units whose HierarchyIndex is greater than the HierarchyIndex of the selected sibling
                    string updateCommandText = "UPDATE UNIT SET HierarchyIndex = HierarchyIndex + 1 WHERE HierarchyIndex >= @HierarchyIndex AND ParentId = @ParentId";
                    cmd.CommandText = updateCommandText;
                    cmd.Parameters.AddWithValue("HierarchyIndex", hierarchyIndexOfNewSibling);
                    cmd.Parameters.AddWithValue("ParentId", unit.ParentId);
                    cmd.ExecuteNonQuery();

                    // INSERT new sibling
                    string insertCommandText = "INSERT INTO UNIT (Name,TemplateId,CreatedAt,HierarchyIndex,ParentId) VALUES (@Name,@TemplateId,@CreatedAt,@HierarchyIndex,@ParentId);Select Scope_Identity();";
                    cmd.CommandText = insertCommandText;
                    cmd.Parameters.AddWithValue("Name", unit.Name);
                    cmd.Parameters.AddWithValue("TemplateId", unit.TemplateId);
                    cmd.Parameters.Add("CreatedAt", SqlDbType.DateTime2).Value = unit.CreatedAt;
                    unit.UnitId = Convert.ToInt32(cmd.ExecuteScalar());

                    trans.Complete();
                } 
            }
        }
4

1 に答える 1

0

dataProviderクラスで接続プールを使用できます。

これにより、接続を再利用できますが、アプリケーションをマルチスレッド化する場合、このアプローチで問題が発生します。接続プールにスレッドセーフな実装があることを確認しない限り、これは口で言うほど簡単ではありません。

于 2012-11-02T11:50:28.960 に答える