作为具有PHP背景的开发人员我总是在两个独立的函数中将连接分离到DB和Query。逻辑是为什么我应该调用Connect();每次我想查询到DB?这不是很贵吗?
现在我正在开发一个使用C#和SQL Server 2016的项目,并遇到了以下sample from MSDN。
我注意到他们在一个方法中同时进行连接和查询。这对我来说很奇怪,因为我说我是一名PHP开发人员,所以有几个问题:
SqlConnection.OpenAsync();
?以下是我尝试分离连接和查询的尝试(未经测试):
private SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
private Task<SqlConnection> connection;
private async Task<SqlConnection> ConnectDB()
{
// Build connection string
builder.DataSource = "localhost";
builder.UserID = "user";
builder.Password = "pass";
builder.InitialCatalog = "test";
// Connect to SQL
SqlConnection connection = new SqlConnection(builder.ConnectionString);
await connection.OpenAsync();
return connection;
}
private async void Query(string cmd)
{
if (cmd == string.Empty || cmd == null)
{
throw new ArgumentException("Query string is empty or null.");
}
SqlCommand command = new SqlCommand(cmd, connection.Result);
await command.ExecuteNonQueryAsync();
}
// Main Form Constructor
public MainForm()
{
connection = ConnectDB();
}
// Example usage?
private void GetAll()
{
Query("SELECT * FROM `test`");
}
答案 0 :(得分:1)
1)仅针对你的第一个问题。 ADO.NET保留了一个连接池,因此只要连接字符串没有变化,打开新连接的性能就不会那么差。
2)阅读完样本后,使用“using”关键字作为using语句。当以这种方式使用时,包含在using关键字中的对象一旦超出范围就将被处理(关闭)。注意,using关键字在C#中有两个用途。它们现在都在下面链接,只是注意到你对第二个链接感兴趣。
3)我更喜欢将连接和查询保持在一起。我认为这被认为是最佳做法。我不一定会说这是不好的做法,但我个人会避免它。
保持数据库连接打开更长时间然后它需要活着的原因令人不悦。
假设您有一个具有SqlConnection,SqlCommand和SqlDataReader属性/字段实例的类。如果出于某种原因需要在另一个命令已经运行时触发命令,则必须打开一个新的SqlDataReader来执行另一个查询,因为底层类组件不能同时处理多个查询。这里唯一真正的问题是SqlDataReader。理论上你可以通过在需要时创建该类型的实例并在类中保留一个SqlCommand和SqlConnection实例来解决这个问题,但我建议不来做到这一点。
最后,如果你保留了类范围的实例,你的类需要实现IDisposable并处理所有这些对象。然而,如果在每种方法中都适当地处理了所有对象,则没有必要。
只是更容易避免在类中保留这些类型的属性/字段实例。
(对不起,我开始说#3很差)
答案 1 :(得分:0)
1)如上所述,.NET保留了一个连接池,并将重新使用幕后连接,以减少每次重新连接到数据库的开销。 Connection Pooling
2)在示例代码中,当代码退出using块时,将在连接对象上调用Dispose
,它会自动关闭它。有关详细信息,请参阅this问题。
3)就个人而言,我更喜欢将连接和查询保持在一起;将它们分开几乎没有性能优势,并且当你完成连接时,更难以确保连接关闭并妥善处理。