考虑以下课程
public class DataManager
{
private SqlConnection cn;
public SqlCommand cmd;
public DataManager(bool initializeCmd=true)
{
string conString="server=192.168.1.20;User Id=sa;pwd=123;Persist Security Info=True; database=testDB";
cn = new SqlConnection(conString);
if (initializeCmd)
cmd = new SqlCommand();
}
public void OpenDbConnection()
{
if (cn.State == ConnectionState.Closed)
cn.Open();
}
public void CloseDbConnection()
{
if (cn.State == ConnectionState.Open)
cn.Close();
}
public bool Update_Database()
{
cmd.Connection = cn;
OpenDbConnection();
int n=cmd.ExecuteNonQuery();
CloseDbConnection();
if(n>0) { return true; }
else { return false; }
}
public bool Update_Database(string cmdTxt, bool isProcedure)
{
cmd = new SqlCommand(cmdTxt, cn);
if (isProcedure)
cmd.CommandType = CommandType.StoredProcedure;
else
cmd.CommandType = CommandType.Text;
OpenDbConnection();
int n=cmd.ExecuteNonQuery();
CloseDbConnection();
if(n>0) { return true; }
else { return false; }
}
}
现在考虑第二课
public class staff
{
DataManager dm;
public bool resetPwd(string code)
{
dm = new DataManager(false);
string query= "UPDATE Staff WHERE pwd='123' WHERE code="+code;
return dm.Update_Database(query,false);
}
public bool changePwd(string code,string pwd)
{
dm = new DataManager();
dm.cmd.CommandText = "UPDATE Staff WHERE pwd=@pwd WHERE code=@code";
dm.cmd.Parameters.Clear();
dm.cmd.Parameters.AddWithValue("@code", code);
dm.cmd.Parameters.AddWithValue("@code", code);
return dm.Update_Database();
}
}
DataManager类是处理数据库操作的通用类。现在我的问题是是否有任何方法可以阻止我使用
Update_Database()
如果我打电话
dm = new DataManager(false)
而不是
dm = new DataManager()
来自员工班。因为如果我使用dm = new DataManager(false),它将抛出一个错误,因为sql命令对象没有初始化。
答案 0 :(得分:2)
没有什么可以阻止其他人初始化dm = new DataManager(true)
。如果您需要数据库更新不可用,请将其从DataManager
移开。创建另一个DatabaseUpdater
类,负责数据库更新操作。注意:Update
方法的名称具有误导性 - 它们应该执行UPDATE查询,但我可以传递DELETE查询文本并执行它。
DataManager
的BTW有用性是有争议的。 ADO.NET使用connection pooling来最小化打开连接的成本。硬编码连接字符串也不是一个好主意。使用配置文件的connectionStrings部分来提供它们。
我建议您查看Dapper库,这将使您的代码看起来像这样:
public bool ChangePassword(string code, string pwd)
{
using(DbConnection conn = GetConnection())
{
string sql = "UPDATE Staff SET pwd=@pwd WHERE code=@code";
int updatedRowsCount = conn.Query<int>(sql, new { code, pwd }).First();
return updatedRowsCount == 1;
}
}
连接将自动打开和关闭。将创建命令,并将所有参数添加到命令。我没有提供GetConnection
实现 - 它有责任读取连接字符串并返回新连接。
最后一个建议 - 避免接受布尔参数的方法。这种参数非常混乱。 DataManager(true)
的含义是什么?它与DataManager(false)
的区别如何?
答案 1 :(得分:1)
您无法自动“显示和隐藏”功能。一旦您的代码编译,就无法动态更改。
你可以做什么,哪个不那么“整洁”要么抛出异常,要么根本不运行代码。这是非常糟糕的界面设计,因为它会产生无法轻易理解的行为。
如果您真的想要,可以设置DataManager以接收数据库连接字符串:
string connectionString = "...";
DataManager dm = new DataManager(connectionString);
如果实现者不知道连接字符串,他们将无法打开连接。
这不是“最佳设计”,但它可以回答您的问题。
答案 2 :(得分:0)
更好的解决方案可能只是在命令可用时公开bool属性。这样,消费者可以首先测试该方法是否被允许。如果他们仍想调用它,则抛出异常。
重要的是,他们有能力为自己进行测试。
.NET 4.5可能4,介绍了动态类对象,它可以在运行时更改方法。我不想在我的代码中以这种方式使用它,但它就在那里。
答案 3 :(得分:0)
为什么在执行initializeCmd == true
之前(从函数内部)检查是否Update_Database()
。如果它的值是false
(只返回),请执行NOP。您可以将SqlCommand
初始化为默认值,以便调用该方法不会产生任何副作用。或者在执行前检查命令是否为null。您还可以将继承用于不同的专门类行为。
编辑:
如果您不喜欢#warning
,图书馆Code Contracts for .NET可以帮助您显示警告,具体取决于课程的使用情况。
代码约定是从任何.NET程序使用的静态库方法,用于指定代码的行为。
使用该库可以使用静态检查来检查合同违规。 (如果你真的认为这是必要的!)