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