C# 业务服务在数据访问层上调用多个方法,每个方法打开一个连接
我在unitservice中执行此伪代码,它调用UnitDataProvider类的2个方法C# 业务服务在数据访问层上调用多个方法,每个方法打开一个连接,c#,database-connection,data-access-layer,business-logic-layer,C#,Database Connection,Data Access Layer,Business Logic Layer,我在unitservice中执行此伪代码,它调用UnitDataProvider类的2个方法 var units = dataProvider.GetChildrenUnits(parentId); unit.HierarchyIndex = units.Where( u => u.TemplateId == unit.TemplateId && u.ParentId == null).Max( u => u.HierarchyIndex) + 1; dataProv
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个连接或重用打开的连接
或者您认为对于每个dataprovider方法调用,连接是正常的吗
解决方案:数据库上的所有数据访问逻辑都是在DAL中完成的,而不是BLL,因为我认为下面的内容对于我的业务来说不是业务逻辑,只是数据库逻辑
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();
}
}
}
您可以在dataProvider类中使用连接池
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);
这将允许您重用连接,但如果您希望应用程序是多线程的,则此方法将出现问题。除非您确保您的连接池具有线程安全的实现,这说起来容易做起来难。ok上述方法不完整。现在该方法有3个dataprovider调用。一个GetXX、一个updatesblings和一个AddSibling。您如何看待在UnitService中使用TransactionScope,它跨越了所有3种数据提供程序方法。然后,每个dataprovider方法还必须传递一个连接对象。你觉得怎么样?这可能行得通,但我很好奇你会怎样把它抽象出来,让它从外面看不见。此外,应用程序是基于web还是基于桌面?它是一个asp.net mvc web应用程序。你说“…所以从外面看不见…”是什么意思?AddSibling(UnitUnitUnit)现在正在调用3个dataprovider方法,每个方法同时传递一个连接对象。事务在服务中启动和完成。你认为问题出在哪里?你能不能换个说法?为什么不在每个请求中使用一个连接呢?这正是我之前说过的。TransactionScope跨越3个方法,每个方法都接受一个打开的连接对象。这是你担心的吗?