我几个月前在MSDN上阅读了一篇文章,并且最近开始使用以下代码片段来执行ADO.NET代码,但我觉得它可能很糟糕。我是在反应还是完全可以接受?
private void Execute(Action<SqlConnection> action)
{
SqlConnection conn = null;
try {
conn = new SqlConnection(ConnectionString);
conn.Open();
action.Invoke(conn);
} finally {
if (conn != null && conn.State == ConnectionState.Open) {
try {
conn.Close();
} catch {
}
}
}
}
public bool GetSomethingById() {
SomeThing aSomething = null
bool valid = false;
Execute(conn =>
{
using (SqlCommand cmd = conn.CreateCommand()) {
cmd.CommandText = ....
...
SqlDataReader reader = cmd.ExecuteReader();
...
aSomething = new SomeThing(Convert.ToString(reader["aDbField"]));
}
});
return aSomething;
}
答案 0 :(得分:8)
当你这样做时,有什么意义呢?
public SomeThing GetSomethingById(int id)
{
using (var con = new SqlConnection(ConnectionString))
{
con.Open();
using (var cmd = con.CreateCommand())
{
// prepare command
using (var rdr = cmd.ExecuteReader())
{
// read fields
return new SomeThing(data);
}
}
}
}
您可以通过执行此类操作来促进代码重用。
public static void ExecuteToReader(string connectionString, string commandText, IEnumerable<KeyValuePair<string, object>> parameters, Action<IDataReader> action)
{
using (var con = new SqlConnection(connectionString))
{
con.Open();
using (var cmd = con.CreateCommand())
{
cmd.CommandText = commandText;
foreach (var pair in parameters)
{
var parameter = cmd.CreateParameter();
parameter.ParameterName = pair.Key;
parameter.Value = pair.Value;
cmd.Parameters.Add(parameter);
}
using (var rdr = cmd.ExecuteReader())
{
action(rdr);
}
}
}
}
您可以像这样使用它:
//At the top create an alias
using DbParams = Dictionary<string, object>;
ExecuteToReader(
connectionString,
commandText,
new DbParams() { { "key1", 1 }, { "key2", 2 } }),
reader =>
{
// ...
// No need to dispose
}
)
答案 1 :(得分:1)
恕我直言,这确实是一种不好的做法,因为你正在为你执行的每个语句创建并打开一个新的数据库连接。
为什么不好:
性能方面(虽然连接池有助于降低性能):您应该打开连接,执行必须执行的语句,并在不知道下一个语句何时将关闭时关闭连接执行。
但肯定是在背景方面。我的意思是:你将如何处理交易?您的交易边界在哪里?您的应用程序层知道何时必须启动和提交事务,但是您无法使用这种工作方式将多个语句跨越到同一个sql-transaction中。
答案 2 :(得分:0)
这是可以接受的。我两年前创建了一个SqlUtilities类,它有类似的方法。如果你愿意,你可以更进一步。
编辑:无法找到代码,但我输入了一个小例子(可能有很多语法错误;)
<强> SQLUtilities 强>
public delegate T CreateMethod<T> (SqlDataReader reader);
public static T CreateEntity<T>(string query, CreateMethod<T> createMethod, params SqlParameter[] parameters) {
// Open the Sql connection
// Create a Sql command with the query/sp and parameters
SqlDataReader reader = cmd.ExecuteReader();
return createMethod(reader);
// Probably some finally statements or using-closures etc. etc.
}
致电代码
private SomeThing Create(SqlDataReader reader) {
SomeThing something = new SomeThing();
something.ID = Convert.ToIn32(reader["ID"]);
...
return something;
}
public SomeThing GetSomeThingByID (int id) {
return SqlUtilities.CreateEntity<SomeThing> ("something_getbyid", Create, ....);
}
当然你可以使用lambda表达式而不是Create方法,你可以轻松地创建一个CreateCollection方法并重用现有的Create方法。
但是,如果这是一个新项目。查看实体的LINQ。比ADO.Net更容易和灵活。
答案 3 :(得分:0)
这是一种非常合理的使用方法。
通过将连接逻辑包装到采用Action<SqlConnection>
的方法中,您可以帮助防止重复代码和引入错误的可能性。由于我们现在可以使用lambdas,这将成为处理这种情况的一种简单,安全的方法。
答案 4 :(得分:0)
嗯,在我看来,在完成它之前检查你做了什么。有效的东西并不意味着它是最好和最好的编程实践。查看并找到一个具体的例子和使用它的好处。但如果你是考虑使用大型项目,使用像NHibernate这样的框架会很好。因为有很多项目甚至是基于它开发的框架,比如http://www.cuyahoga-project.org/。