我今天遇到了以下代码,我不喜欢它。这是相当明显的,但我还是会在这里添加一些解释:
基本上,它从数据库中读取应用程序的所有设置,并遍历所有这些设备,查找数据库版本和APP版本,然后将一些变量设置为数据库中的值(稍后将使用)。
我看着它并认为它有点难看 - 我不喜欢switch语句而且我讨厌在完成后继续遍历列表的事情。所以我决定重构它。
我向大家提出的问题是你如何重构它?或者你认为它甚至需要重构?
以下是代码:
using (var sqlConnection = new SqlConnection(Lfepa.Itrs.Framework.Configuration.ConnectionString))
{
sqlConnection.Open();
var dataTable = new DataTable("Settings");
var selectCommand = new SqlCommand(Lfepa.Itrs.Data.Database.Commands.dbo.SettingsSelAll, sqlConnection);
var reader = selectCommand.ExecuteReader();
while (reader.Read())
{
switch (reader[SettingKeyColumnName].ToString().ToUpper())
{
case DatabaseVersionKey:
DatabaseVersion = new Version(reader[SettingValueColumneName].ToString());
break;
case ApplicationVersionKey:
ApplicationVersion = new Version(reader[SettingValueColumneName].ToString());
break;
default:
break;
}
}
if (DatabaseVersion == null)
throw new ApplicationException("Colud not load Database Version Setting from the database.");
if (ApplicationVersion == null)
throw new ApplicationException("Colud not load Application Version Setting from the database.");
}
答案 0 :(得分:16)
我的两分钱......
答案 1 :(得分:2)
代码中存在轻微的低效率(大量字符串分配和不必要的查找)。
结果代码如下所示:
using (var sqlConnection = new SqlConnection(Lfepa.Itrs.Framework.Configuration.ConnectionString))
{
sqlConnection.Open();
using(var selectCommand = new SqlCommand(Lfepa.Itrs.Data.Database.Commands.dbo.SettingsSelAll, sqlConnection))
{
using (var reader = selectCommand.ExecuteReader())
{
while (reader.Read())
{
string val = reader.GetString(reader.GetOrdinal(SettingKeyColumnName));
if ( string.IsNullOrEmpty(val) )
continue;
if ( val.Equals(DatabaseVersionKey, StringComparison.OrdinalIgnoreCase))
DatabaseVersion = new Version(val);
else if (val.Equals(ApplicationVersionKey, StringComparison.OrdinalIgnoreCase))
ApplicationVersion = new Version(val);
}
}
}
}
if (DatabaseVersion == null)
throw new ApplicationException("Could not load Database Version Setting from the database.");
if (ApplicationVersion == null)
throw new ApplicationException("Could not load Application Version Setting from the database.");
答案 2 :(得分:1)
这段代码实际上做了两件事:
1) Get the database version
2) Get the application version
唯一的共性是数据存储方法
我建议重构有三种方法:
// Get the entire dataset from the database using the SettingsSelAll command.
private DataTable GetVersionData() {...}
// Parse a version from the dataset.
private Version GetVersion(string versionName, DataTable dataSet) { ... }
public Version GetVersion(string versionName)
{
DataTable table = GetVersionData();
return GetVersion(versionName, table);
}
这在获取数据和实际使用数据之间强制分离,这总是需要的目标。建议使用一种缓存形式以避免两次执行查询,我建议可以使用方法同时执行数据库和应用程序版本调用。
答案 3 :(得分:1)
据推测,设置表中还有其他有用的值。我建议将所有值读入应用程序持有的字典中。然后根据需要查找值。与稍后再建立另一个连接并重新执行相同查询相比,获取所有记录而不仅仅是这两个记录所增加的费用是微不足道的。
答案 4 :(得分:0)
使用if而不是开关少于5个案例,它会更快。
答案 5 :(得分:0)
我会重写查询,以便返回包含两列的单个记录。这将摆脱using()语句中的条件。正如加布所说,我要加上
if (DatabaseVersion != null && ApplicationVersion != null) break;
在使用区内。
答案 6 :(得分:0)
我要补充的一个建议是在执行更多命令之前执行检查以确保已建立与数据库的连接。
sqlConn.Open();
if (sqlConn.State == ConnectionState.Open)
{
// perform read settings logic here
}
答案 7 :(得分:0)
如果您希望通过更多设置来实现可持续性和扩展,请设置一个策略模式,用于存储处理字典中特定设置的每个策略以及相关的Key值,以便将正确的策略拉出来替换switch语句。