在類庫專案中重複建立 SqlConnection 不僅冗餘,更易導致連線洩漏。本文說明為何應避免在每個方法中 `new SqlConnection()`,並示範使用連線字串設定檔、依賴注入或連線工廠模式集中管理連線生命週期。
private SqlConnection MyConn() {
string setting = ConfigurationManager.ConnectionStrings["myConnectionString"].ToString();
SqlConnection thisConn = new SqlConnection(setting);
return thisConn;
}
public string req_title(int id) {
SqlConnection QConn = MyConn(); // 每次呼叫都 new 連線
SqlDataAdapter myDap = new SqlDataAdapter("select article_title from t_article where art_id=" + id, QConn);
DataSet myDS = new DataSet();
myDap.Fill(myDS, "t_article");
return (myDS.Tables[0].Rows[0][0].ToString());
}
缺點:
Close/Dispose 會洩漏。id)。System.Configuration,難以單元測試。// 介面定義(方便測試替換)
public interface IDbConnectionFactory
{
IDbConnection CreateConnection();
}
// 實作
public class SqlConnectionFactory : IDbConnectionFactory
{
private readonly string _connStr;
public SqlConnectionFactory(string connStr) => _connStr = connStr;
public IDbConnection CreateConnection() => new SqlConnection(_connStr);
}
public class ArticleRepository
{
private readonly IDbConnectionFactory _factory;
public ArticleRepository(IDbConnectionFactory factory) => _factory = factory;
public string GetTitle(int id)
{
using (var conn = _factory.CreateConnection())
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "SELECT article_title FROM t_article WHERE art_id = @id";
cmd.Parameters.AddWithValue("@id", id);
conn.Open();
return cmd.ExecuteScalar()?.ToString();
}
}
}
// Startup.cs
services.AddTransient(_ =>
new SqlConnectionFactory(Configuration.GetConnectionString("Default")));
services.AddTransient();
using Dapper;
public string GetTitle(int id)
{
using (var conn = _factory.CreateConnection())
{
return conn.QueryFirstOrDefault(
"SELECT article_title FROM t_article WHERE art_id = @id", new { id });
}
}