很抱歉一开始只留下了评论,但我几乎每天都会发表类似的评论,因为许多人认为将 ADO.NET 功能封装到 DB-Class(我在10年前也是这样认为)是明智的选择。大多数人决定使用静态/共享对象,因为它似乎比为每个操作创建一个新对象更快。
从性能和故障安全性来看,这既不明智也不可取。
不要侵犯连接池的领地
ADO.NET 内部管理与DBMS之间底层连接的原因有很好的解释: ADO-NET 连接池。
实际上,大多数应用程序仅使用一个或几个不同的连接配置。这意味着在应用程序执行期间,将重复打开和关闭许多相同的连接。为了最小化打开连接的成本,ADO.NET使用一种名为连接池的优化技术。
连接池可以减少必须打开新连接的次数。池管理器维护物理连接的所有权。它通过保持每个给定连接配置的一组活动连接来管理连接。每当用户在连接上调用Open时,池管理器会在池中查找可用的连接。如果有可用的池连接,则返回给调用者而不是打开新连接。当应用程序在连接上调用Close时,池管理器将其返回到活动连接的池集合而不是关闭它。一旦连接返回到池中,它就可以在下一次Open调用上被重用。
很明显,没有理由避免创建、打开或关闭连接,因为实际上它们根本没有被创建、打开和关闭。这只是一个标志,用于连接池知道何时可以重复使用连接。但这是非常重要的标志,因为如果一个连接正在使用中(连接池认为),必须打开一个新的物理连接到数据库管理系统,这是非常昂贵的。
所以你不会获得任何性能改进,反之亦然。如果达到了指定的最大池大小(默认值为100),甚至会出现异常(太多的打开连接...)。这不仅会极大地影响性能,还会成为令人讨厌的错误和(没有使用事务)数据转储区域。
如果您甚至使用静态连接,则为尝试访问此对象的每个线程创建锁定。ASP.NET本质上是一个多线程环境。因此,这些锁定可能导致性能问题。实际上,迟早会出现许多不同的异常(如ExecuteReader需要打开并可用的连接)。
结论:
- 不要重用连接或任何ADO.NET对象。
- 不要使它们静态/共享(在VB.NET中)
- 在您需要它们的地方(例如在方法中),始终创建、打开(在连接的情况下)、使用、关闭和处理它们
- 使用
using-statement
隐式释放和关闭(在连接的情况下)
这不仅适用于连接(尽管最为明显)。实现IDisposable
接口的每个对象都应该被处理掉(最简单的方式是使用using-statement
),特别是在System.Data.SqlClient
命名空间中。
上述所有内容都反对自定义DB-Class,该类封装并重复使用所有对象。这就是我建议废弃它的原因。它只会带来问题。
编辑:这是您的retrievePromotion
方法的可能实现:
public Promotion retrievePromotion(int promotionID)
{
Promotion promo = null;
var connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["MainConnStr"].ConnectionString;
using (SqlConnection connection = new SqlConnection(connectionString))
{
var queryString = "SELECT PromotionID, PromotionTitle, PromotionURL FROM Promotion WHERE PromotionID=@PromotionID";
using (var da = new SqlDataAdapter(queryString, connection))
{
var tblPromotion = new DataTable();
da.SelectCommand.Parameters.Add("@PromotionID", SqlDbType.Int);
da.SelectCommand.Parameters["@PromotionID"].Value = promotionID;
try
{
connection.Open();
da.Fill(tblPromotion);
if (tblPromotion.Rows.Count != 0)
{
var promoRow = tblPromotion.Rows[0];
promo = new Promotion()
{
promotionID = promotionID,
promotionTitle = promoRow.Field<String>("PromotionTitle"),
promotionUrl = promoRow.Field<String>("PromotionURL")
};
}
}
catch (Exception ex)
{
throw;
}
}
}
return promo;
}
conString
从性能方面来说也没有任何加成,因为默认情况下它会被缓存,就像当前应用程序中的每个配置值一样。 - Tim Schmelter