C# 业务服务在数据访问层上调用多个方法,每个方法打开一个连接

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

我在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;
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个方法,每个方法都接受一个打开的连接对象。这是你担心的吗?