c# - 在 C# 中处理数据库连接
问题描述
我正在使用 C# 和 SqlServer 创建 WinForm 应用程序。我必须在上面处理许多数据库 CRUD 查询。而且还有很多表格和很多控制器。
现在我想知道的是,如果我使用许多方法创建用于处理数据库连接的通用类,用于打开连接、关闭连接、执行 Sql 命令或进行任何其他数据检索。这种方法是好是坏?
或以下运行每个查询的方法是好是坏?
using (SqlConnection connection = new SqlConnection("Integrated Security=SSPI;Initial Catalog=MYDB"))
{
connection.Open();
// Pool A is created.
}
哪种方法对性能和安全性更好?
解决方案
以下是使用连接时需要考虑的一些要点。
1) 使用 using 语句在不再需要连接对象时立即处理它:
using (var conn = new SqlConnection(connectionstring))
{
// your sql magic goes here
}
2) 如果您不立即处理对象,则可以使用 try-finally 语句确保连接已关闭:
var conn = new SqlConnection(connectionstring);
try
{
// do sql shizzle
}
finally
{
conn.Close();
}
3)为了防止SQL注入,使用参数化查询,从不连接字符串
using (var conn = new SqlConnection(connectionstring))
{
conn.Open();
using(var comm = new SqlCommand("select * from FooBar where foo = @foo", conn))
{
comm.Parameters.Add(new SqlParameter("@foo", "bar"));
// also possible:
// comm.Parameters.AddWithValue("@foo", "bar");
using(var reader = comm.ExecuteReader())
{
// Do stuff with the reader;
}
}
}
4) 如果您正在执行多个更新、插入或删除语句,并且它们都需要一次成功,请使用事务:
using (var conn = new SqlConnection(connectionstring))
{
conn.Open();
using(var trans = conn.BeginTransaction())
{
try
{
using(var comm = new SqlCommand("delete from FooBar where fooId = @foo", conn, trans))
{
comm.Parameters.Add(new SqlParameter { ParameterName = "@foo", DbType = System.Data.DbType.Int32 });
for(int i = 0; i < 10 ; i++)
{
comm.Parameters["@foo"].Value = i;
comm.ExecuteNonQuery();
}
}
trans.Commit();
}
catch (Exception exe)
{
trans.Rollback();
// do some logging
}
}
}
5)存储过程的使用类似:
using (var conn = new SqlConnection(connectionstring))
{
conn.Open();
using (var comm = new SqlCommand("FooBarProcedure", conn) { CommandType = CommandType.StoredProcedure })
{
comm.Parameters.Add(new SqlParameter("@FooBar", "shizzle"));
comm.ExecuteNonQuery();
}
}
(源存储过程:this Answer)
多线程:使用多线程和 SQL 连接的最安全方法是始终关闭和处置您的连接对象。这是 SqlConnection 设计的行为。(来源:回答约翰斯基特)
推荐阅读
- html - 在图标旁边对齐文本或跨越 unicode 字符
- csv - 如何使用 c# 将 csv 文件转换为制表符分隔的 .txt 文件
- excel - 在 For 循环中使用 Sumif 公式
- r - 我们可以对 readlines 和 rbind 做并行处理吗
- android-emulator - 无法通过 appium-RobotFramework 连接到 Android 模拟器
- php - 当用户离开 Woocommerce 中的结帐页面时删除应用的优惠券
- marklogic - MarkLogic 是如何计算米每小时数据的?
- oracle - 子查询返回多行
- javascript - 解决最小化关键请求深度 - 页面性能
- java - 是否可以配置 Zuul 路由以匹配通配符?