【发布时间】:2016-04-06 05:33:31
【问题描述】:
我最近开始在一个拥有数千行遗留代码的新项目中工作。我们面临着几个性能问题。我决定看一下代码并看到以下内容。有一堂课:
public class BaseDataAccess
{
private Database dB;
public Database DB
{
get
{
if (dB == null)
{
dB = DatabaseFactory.CreateDatabase();
}
return dB;
}
}
}
还有许多继承自前一个基类的后代类。在内部,那些其他类使用 DB 属性,如下所示:
DataSet ds = DB.ExecuteDataSet(spGetCustomersSortedByAge);
最后,有一个庞大的类(5000 行代码),其中包含数十种方法,如下所示:
public void ProcessPayments()
{
try
{
List<Employee> employees = new EmployeesDA().SelectAll(null);
foreach (Employee employee in employees)
{
employee.Account = new MovementsDA().SelectAll(employee.Id, DateTime.Now);
...
City city = new CitiesDA().Select(zone.cityId);
...
Management m = new ManagmentDA().Select(city.id);
}
}
catch (Exception ex)
{
...
}
}
注意在前面的方法中,EmployeesDA、MovementsDA、CitiesDA 和 ManagmentDA 都是 BaseDataAccess 的继承者,并且在内部使用它们各自的 DB 属性。另请注意,它们在 foreach 循环中不断被实例化(很多时候在 2 级嵌套中)。
我认为实例化本身是可疑的,但我更关心这里的数据库连接发生了什么?实例化的每个 DA 是否都打开了一个新的底层连接?这段代码有多糟糕?
关于我正在考虑的解决方案的附带说明,以防此代码应该被修复:我正在考虑将每个构造函数设为私有,因此编译器开始抱怨实例化并通过调用 GetInstance 方法重构实例化(单例模式)避免重新创建对象和底层连接。但是,我不确定这是否在某种程度上也可能是危险的,例如,如果连接可能会关闭。当前的代码没有这个问题,因为实例化一直在发生。
【问题讨论】:
-
这种方法有很多问题,但如果
DatabaseFactory.CreateDatabase();方法为每次调用都返回一个新的、已连接的数据库连接,那么您就遇到了很大的连接问题。跨度> -
您遇到的另一个问题是事务支持。
ProcessPayments不应该确保所有事情都发生在一个事务中吗?或者每个员工至少有一笔交易,或者类似的事情? -
处理此问题的正确方法是开始让您的程序中的连接状态可见,并且必须对其进行管理。
-
@LasseV.Karlsen,DatabaseFactory 是一个 .NET 类,但我不确定每次执行 CreateDatabase 时发生了什么。所以我希望有人能在这里有所启发。
-
如果这里的数据库对象只在查询时打开连接,之后又关闭,那么打开很多连接应该没有问题,但还是要考虑事务的问题。
标签: c# .net performance .net-3.5 processing-efficiency