ADO.NET连接和DataAdaptor对象范围的最佳实践

时间:2009-02-27 09:08:46

标签: ado.net

这是我在StackOverflow上的第一篇文章,所以请保持温和......

我对ADO.NET的对象范围有一些疑问。

当我连接到数据库时,我通常使用这样的代码:

OleDbConnection conn = new OleDbConnection("my_connection_string");
conn.Open();
OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * from Employees", conn);
OleDbCommandBuilder cb = new OleDbCommandBuilder(adapter);
DataTable dt = new DataTable();
adapter.Fill(dt);
conn.Close();
conn.Dispose();

假设我将生成的DataTable绑定到网格控件并允许我的用户编辑网格内容。现在,当我的用户按下“保存”按钮时,我需要调用此代码:

adapter.Update(dt);

以下是我的问题:

1)我是否需要保留最初加载数据表时创建的适配器对象,还是可以在“保存”按钮单击事件中创建另一个适配器对象来执行更新?

2)如果我确实需要保留原始适配器对象,是否还需要保持连接对象可用并打开?

我理解ADO.NET的断开模型 - 我只是在更新数据库时对对象范围感到困惑。如果有人能给我一些关于这种情况的最佳实践的指示,我将非常感激!

提前致谢...

3 个答案:

答案 0 :(得分:3)

1)您不需要相同的DataAdapter,但如果您创建一个新的DataAdapter,它必须使用与其基础相同的查询。

2)如果连接关闭,DataAdapter将打开其连接。在这种情况下,它将在完成后再次关闭连接。如果连接已经打开,即使完成连接也会使连接保持打开状态。

通常你会像你的例子一样工作。创建一个Conneciton和一个DataAdapter,填充DataTable并随后处理Connection和DataAdapter。

对您的代码发表两条评论:

  • 您不需要CommandBuilder,因为您只进行选择。仅当您要自动生成Insert,Update或Delete语句时,才需要命令构建器。在这种情况下,您还需要从CommandBuilder手动设置DataAdapter上的InsertCommand,UpdateCommand或DeleteCommand。
  • 二。您应该使用Using子句,而不是手动调用Dispose。它确保即使抛出异常也会处理您的对象。

尝试将代码更改为:

DataTable dt = new DataTable();
using (OleDbConnection conn = new OleDbConnection("my_connection_string"))
using (OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * from Employees", conn))
{
  adapter.Fill(dt);    
}

请注意,我在using子句之外定义了DataTable。这是确保在您离开使用时表格在范围内所必需的。另请注意,您不需要DataAdapter上的Dispose调用或Connection上的Close调用。当你离开使用时,两者都是隐式完成的。

喔。欢迎来到SO: - )

答案 1 :(得分:0)

回答你的问题:

  1. 理想情况下,您应该保留相同的DataAdapter,因为它已经执行了初始化。 DataAdapter提供了诸如SelectCommand,UpdateCommand,InsertCommand和DeleteCommand之类的属性,允许您设置不同的Command对象以在数据源上执行这些不同的功能。因此,您可以看到,DataAdapter的设计可以重用于多个命令(用于相同的数据库连接)。您使用CommandBuilder(但不推荐)通过分析SelectCommand创建其他命令,从而允许您使用相同的CommandBuilder执行更新,删除和插入。

  2. 最好允许DataAdapter隐式处理数据库连接。 @Rr Grimstad 已经详细阐述了这种隐含的行为,理解这一点很有用。理想情况下,应尽快关闭连接。

答案 2 :(得分:0)

还有两个额外的细节值得加入Rune Grimstad的优秀答案。

首先,CommandBuilder(如果需要)实现IDisposable,因此应该包含在它自己的'using'语句中。令人惊讶的是(至少对我来说),处理DataAdapter not 似乎处理关联的CommandBuilder。我没有做到这一点时遇到的问题是,即使我在DataAdapter上调用了Dispose,并且连接状态为“已关闭”,但在使用CommandBuilder更新该数据库后,我无法删除临时数据库。

其次,语句“ ...在这种情况下,您还需要手动设置DataAdapter上的InsertCommand,UpdateCommand或DeleteCommand ...... ”并不总是正确的。对于许多琐碎的情况,CommandBuilder将根据提供给DataAdapter的SELECT语句和来自数据库的元数据自动创建正确的INSERT,UPDATE和DELETE语句。在这种情况下,“Trivial”意味着只访问一个表,并且该表具有作为SELECT语句的一部分返回的主键。