您提出了几个问题,而您向我们展示的代码又提出了一些问题。您可能需要考虑的事情:
尝试将以数据库为中心的活动限制在它们自己的类中。GlobalStats
除了处理从数据库中提取数据并将其变为实际对象的实际类之外,没有其他人需要知道如何为对象返回行列表。没有人。如果其他人确实知道,那么您的班级没有使用信息隐藏(因为我们使用的是面向对象的语言,所以您应该使用)。
如果对象 implements IDisposable
,那么你应该用一个try {} finally {}
块来包装它,或者更好的是,用一个using
语句来包装它(见我下面的第二个例子)。
您的连接字符串应该只能被实际需要它的类访问(分离您的关注点的一部分)。也许有一个包含该信息的基本 DataAccess 类?
public abstract class DataAccess
{
protected const string ConnectionString = "YourConnectionStringHere";
}
然后您的存储库可以从此类继承,并且您没有导致代码不必要地耦合的全局静态常量。
以下是我将如何编写您正在编写的内容(请注意,此代码并不是真正要使用的,仅用于说明目的):
[WebMethod]
public List<GlobalStat> GetStats()
{
GlobalStatsRepository repository = new GlobalStatsRepository();
List<GlobalStat> stats = repository.GetStats();
return stats;
}
数据访问层
public class GlobalStatsRepository
{
public List<GlobalStat> GetStats()
{
string sql = @"SELECT * from GlobalStats"; //no, not a good practice
var stats = new List<GlobalStat>();
try
{
string ConString = Constants.connString;
conn = new SqlConnection(ConString);
cmd = new SqlCommand(sql, conn);
conn.Open();
dr = cmd.ExecuteReader();
while (dr.Read())
{
GlobalStat stat = new GlobalStat();
stat.Key = dr[0].ToString();
stat.Value = int.Parse(dr[1].ToString());
stats.Add(stat);
}
}
catch (SQLDataReaderException ex)
{
logger.Log(ex);
throw;
}
return stats;
}
}
参数化查询示例
public List<GlobalStat> GetStatsById(int id)
{
var stats = new List<GlobalStat>();
string sql = @"SELECT * from GlobalStats WHERE Id = @Id";
using (SqlConnection conn = new SqlConnection(ConString))
{
conn.Open();
using (SQLCommand command = new SqlCommand(sql, conn))
{
command.Parameters.Add(new SqlParameter("Id", id));
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
GlobalStat stat = new GlobalStat();
stat.Key = dr[0].ToString();
stat.Value = int.Parse(dr[1].ToString());
stats.Add(stat);
}
}
}
return stats;
}