在Oracle上构建 .NET 应用程序(1)(2)
错误处理 Try-Catch-Finally 结构的错误处理是 .NET 语言的一部分。 下面是使用 Try-Catch-Finally 语法的一个相对最小的例子: Dim conn As New OracleConnection( oradb) '
错误处理
Try-Catch-Finally 结构的错误处理是 .NET 语言的一部分。 下面是使用 Try-Catch-Finally 语法的一个相对最小的例子:
虽然这种方法将适当地捕获尝试从数据库中获取数据时发生的任何错误,但这种方法对用户却不友好。
Oracle DBA 或开发人员很清楚 ORA-12545 的意义,但是最终用户不清楚。 一种更好的解决方案是添加一条额外的 Catch 语句来捕获最常见的数据库错误并显示对用户友好的消息。
注意上面的代码示例中的两条 Catch 语句。 如果没有捕获到任何 Oracle 错误,那么将跳过第一条 Catch 语句分支,让第二条 Catch 语句来捕获其他任何类型的错误。 在代码中,应该根据从特殊到一般的顺序对 Catch 语句排序。 在实施了对用户友好的异常处理代码之后,ORA-12545 错误消息
Finally 代码将始终执行,而无论错误是否发生。 通过在 Finally 代码块中加入连接对象的 Close 或 Dispose 方法调用,在执行了 Try-Catch-Finally 代码段之后,数据库连接将始终关闭。 试图关闭没有打开的数据库连接不会导致错误。 例如,如果数据库不可用,数据库连接没有打开,那么 Finally 代码块将试图关闭不存在的连接。 执行多余的 Close 或 Dispose 是无效的。 只需将一条 Close 或 Dispose 方法放到 Finally 代码块中,将保证关闭连接。
利用 DataReader 检索多个值
到目前为止,我们的示例仅说明了如何检索单个值。 DataReader 可以检索多列和多行的值。 首先进行多行、单列的查询:
select deptno, dname, loc from dept where deptno = 10
要获取列的值,可以使用以零为基数的序号或列名。 序号与查询中的顺序相关。 因而,可以在 VB.NET 中通过使用 dr.Item(2) 或 dr.Item("loc") 来查询 loc 列的值。
下面是将 dname 和来自上一查询的 loc 列串连起来的代码段:
现在我们进行返回多行的查询:select deptno, dname, loc from dept
要处理从 DataReader 中返回的多行,需要某种类型的循环结构。 此外,需要一个可以显示多行的控件。 DataReader 是一个仅正向的只读游标,因此不能将其与可更新或完全可滚动的控件(如 Windows Forms DataGrid 控件)捆绑在一起。 DataReader 与 ListBox 控件兼容,如以下代码段所示:
While dr.Read() ' VB.NET ListBox1.Items.Add("The " + dr.Item(1) + " department is in " + dr.Item("loc")) End Whilewhile (dr.Read()) // C#{ listBox1.Items.Add("The " + dr.GetString(1) + " department is in " + dr.GetString(2);}
上机操作 3(利用 DataReader 检索多列和多行)重点介绍了这些概念中的一部分。
总结
本文向您介绍了使用 VS.NET 编程语言访问 Oracle 数据库的过程。 您现在应该能够连接数据库并检索多列和多行。
John Paul Cook (johnpaulcook@email.com) 是居住在休斯顿的一位数据库和 .NET 顾问。 他撰写了许多关于 .NET、Oracle 和其他主题的文章,并从 1986 年以来一直开发关系数据库应用程序。他目前的兴趣包括 Visual Studio 2005 和 Oracle 10g。 他是 Oracle 认证 DBA 和 Microsoft MCSD for .NET。
上机操作 1: 从数据库中检索数据
首先向 Windows 表单添加一个按钮控件和一个标签控件。 务必在这些控件上方保留空间,以便在上机操作 2 中添加控件。
添加代码,它们用于从 Oracle 数据库中检索数据并在表单上显示结果。 将代码放在按钮的单击事件处理程序中。 开始这项任务的最容易的方式是双击该按钮,因为它将为事件处理程序创建一个 stub。
在 Public Class 声明之前添加 VB.NET Imports 语句,或在命名空间声明之前添加 C# using 语句。
Imports System.Data ' VB.NETImports Oracle.DataAccess.Client ' ODP.NET Oracle managed providerusing System.Data; // C#using Oracle.DataAccess.Client; // ODP.NET Oracle managed provider
在 Private Sub 和 End Sub 语句之间添加 VB.NET 版本 事件语句代码(确保用您的服务器的主机名称替代 OTNSRVR):
将以下 C# 代码添加到按钮的单击事件处理程序中的括号 { 和 } 之间,并确保用您的服务器的主机名称替代 OTNSRVR:
运行应用程序。 单击按钮。 您将看到以下内容:
上机操作 2: 增加交互性
现在在代码中实施了数据库访问的基础,下一步是为应用程序增加交互性。 可以添加一个文本框来接收用户输入的部门号码 (deptno),而不是运行硬编码的查询。
向表单中添加一个文本框控件和另一个标签控件: 将 Label2 控件的文本属性设为 Enter Deptno: 并确保没有将 TextBox1 的 Text 属性设为任何东西。
修改定义选择字符串的代码:
cmd.CommandText = "select dname from dept where deptno = " + TextBox1.Text 'VB.NETcmd.CommandText = "select dname from dept where deptno = " + textBox1.Text; // C#
运行应用程序。在 deptno 输入 10,测试应用程序。 输入一个无效的 deptno,重新测试应用程序。 应用程序将退出。
修改代码以防止在输入无效的 deptno 时出现错误。 让我们回顾一下,ExecuteReader 方法实际返回一个对象。
If dr.Read() Then ' VB.NET Label1.Text = dr.Item("dname")Else Label1.Text = "deptno not found"End Ifif (dr.Read()) // C#{ label1.Text = dr.Item("dname");}Else{ label1.Text = "deptno not found";}
输入不存在的 deptno 数字,测试应用程序。 现在应用程序不再退出。 输入字母 A 代替数字,然后单击按钮。 应用程序退出。 很明显,我们的应用程序需要更好的方法以处理错误。
可能有人会指出,应用程序应当不充许用户进行将导致错误的无效输入,但最终应用程序必须添加强健的错误处理功能。 不是所有的错误都是可预防的,因此必须实施错误处理。
上机操作 3: 利用 DataReader 检索多行和多列
现在检索了单个值,下一步就是利用 DataReader 检索多行和多列。 添加一个 ListBox 控件到表单中,以显示结果。
添加一个 ListBox 控件到表单中。 重新调整控件的大小,以填满表单的大部分宽度。
从查询中删除 where 子句,并添加以下列:
cmd.CommandText = "select deptno, dname, loc from dept" ' VB.NETcmd.CommandText = "select deptno, dname, loc from dept"; // C#
修改 VB.NET 代码,最终结果如下:
修改您的 C# 代码,最终结果如下:
提供代码下载中已经实施了错误处理。(责任编辑:铭铭)
Try-Catch-Finally 结构的错误处理是 .NET 语言的一部分。 下面是使用 Try-Catch-Finally 语法的一个相对最小的例子:
Dim conn As New OracleConnection( oradb) ' VB.NETTry conn.Open() Dim cmd As New OracleCommand cmd.Connection = conn cmd.CommandText = "select dname from dept where deptno = " + TextBox1.Textcmd.CommandType = CommandType.Text If dr.Read() Then Label1.Text = dr.Item("dname") ' or use dr.Item(0) End IfCatch ex As Exception ' catches any error MessageBox.Show(ex.Message.ToString())Finally conn.Dispose( )End TryOracleConnection conn = new OracleConnection(oradb); // C#try{conn.Open();OracleCommand cmd = new OracleCommand();cmd.Connection = conn; cmd.CommandText = "select dname from dept where deptno = " + textBox1.Text;cmd.CommandType = CommandType.Text; if (dr.Read()) // C# { label1.Text = dr.GetString(0); }}catch (Exception ex) // catches any error{ MessageBox.Show(ex.Message.ToString());}finally{ conn.Dispose();} |
Oracle DBA 或开发人员很清楚 ORA-12545 的意义,但是最终用户不清楚。 一种更好的解决方案是添加一条额外的 Catch 语句来捕获最常见的数据库错误并显示对用户友好的消息。
Catch ex As OracleException ' catches only Oracle errors If InStr(1, ex.Message.ToString(), "ORA-1:", CompareMethod.Text) Then MessageBox.Show( "Error attempting to insert duplicate data.") ElseIf InStr(1, ex.Message.ToString(), "ORA-12545:", CompareMethod.Text) Then MessageBox.Show("The database is unavailable.") Else MessageBox.Show("Database error: " + ex.Message.ToString()) End IfCatch ex As Exception ' catches any error MessageBox.Show (ex.Message.ToString())catch (OracleException ex) // catches only Oracle errors{ switch (ex.Number) {case 1: MessageBox.Show("Error attempting to insert duplicate data.");break; case 12545: MessageBox.Show( "The database is unavailable."); break; default: MessageBox.Show( "Database error:" + ex.Message.ToString()); break; } }catch (Exception ex) // catches any error{ MessageBox.Show(ex.Message.ToString());} |
注意上面的代码示例中的两条 Catch 语句。 如果没有捕获到任何 Oracle 错误,那么将跳过第一条 Catch 语句分支,让第二条 Catch 语句来捕获其他任何类型的错误。 在代码中,应该根据从特殊到一般的顺序对 Catch 语句排序。 在实施了对用户友好的异常处理代码之后,ORA-12545 错误消息
Finally 代码将始终执行,而无论错误是否发生。 通过在 Finally 代码块中加入连接对象的 Close 或 Dispose 方法调用,在执行了 Try-Catch-Finally 代码段之后,数据库连接将始终关闭。 试图关闭没有打开的数据库连接不会导致错误。 例如,如果数据库不可用,数据库连接没有打开,那么 Finally 代码块将试图关闭不存在的连接。 执行多余的 Close 或 Dispose 是无效的。 只需将一条 Close 或 Dispose 方法放到 Finally 代码块中,将保证关闭连接。
利用 DataReader 检索多个值
到目前为止,我们的示例仅说明了如何检索单个值。 DataReader 可以检索多列和多行的值。 首先进行多行、单列的查询:
select deptno, dname, loc from dept where deptno = 10
要获取列的值,可以使用以零为基数的序号或列名。 序号与查询中的顺序相关。 因而,可以在 VB.NET 中通过使用 dr.Item(2) 或 dr.Item("loc") 来查询 loc 列的值。
下面是将 dname 和来自上一查询的 loc 列串连起来的代码段:
Label1.Text = "The " + dr.Item(1) + " department is in " + dr.Item("loc") ' VB.NETLabel1.Text = "The " + dr.GetString(1) + " department is in " + dr.GetString(2); // C# |
现在我们进行返回多行的查询:select deptno, dname, loc from dept
要处理从 DataReader 中返回的多行,需要某种类型的循环结构。 此外,需要一个可以显示多行的控件。 DataReader 是一个仅正向的只读游标,因此不能将其与可更新或完全可滚动的控件(如 Windows Forms DataGrid 控件)捆绑在一起。 DataReader 与 ListBox 控件兼容,如以下代码段所示:
While dr.Read() ' VB.NET ListBox1.Items.Add("The " + dr.Item(1) + " department is in " + dr.Item("loc")) End Whilewhile (dr.Read()) // C#{ listBox1.Items.Add("The " + dr.GetString(1) + " department is in " + dr.GetString(2);}
上机操作 3(利用 DataReader 检索多列和多行)重点介绍了这些概念中的一部分。
总结
本文向您介绍了使用 VS.NET 编程语言访问 Oracle 数据库的过程。 您现在应该能够连接数据库并检索多列和多行。
John Paul Cook (johnpaulcook@email.com) 是居住在休斯顿的一位数据库和 .NET 顾问。 他撰写了许多关于 .NET、Oracle 和其他主题的文章,并从 1986 年以来一直开发关系数据库应用程序。他目前的兴趣包括 Visual Studio 2005 和 Oracle 10g。 他是 Oracle 认证 DBA 和 Microsoft MCSD for .NET。
上机操作 1: 从数据库中检索数据
首先向 Windows 表单添加一个按钮控件和一个标签控件。 务必在这些控件上方保留空间,以便在上机操作 2 中添加控件。
添加代码,它们用于从 Oracle 数据库中检索数据并在表单上显示结果。 将代码放在按钮的单击事件处理程序中。 开始这项任务的最容易的方式是双击该按钮,因为它将为事件处理程序创建一个 stub。
在 Public Class 声明之前添加 VB.NET Imports 语句,或在命名空间声明之前添加 C# using 语句。
Imports System.Data ' VB.NETImports Oracle.DataAccess.Client ' ODP.NET Oracle managed providerusing System.Data; // C#using Oracle.DataAccess.Client; // ODP.NET Oracle managed provider
在 Private Sub 和 End Sub 语句之间添加 VB.NET 版本 事件语句代码(确保用您的服务器的主机名称替代 OTNSRVR):
Dim oradb As String = "Data Source=(DESCRIPTION=(ADDRESS_LIST=" _ + " (ADDRESS=(PROTOCOL=TCP)(HOST=OTNSRVR) (PORT=1521)))" _ + "(CONNECT_DATA=(SERVER=DEDICATED) (SERVICE_NAME=ORCL)));" _ + "User Id=scott;Password= tiger;"Dim conn As New OracleConnection(oradb) ' VB.NETconn.Open()Dim cmd As New OracleCommandcmd.Connection = conncmd.CommandText = "select dname from dept where deptno = 10"cmd.CommandType = CommandType.TextDim dr As OracleDataReader = cmd.ExecuteReader()dr.Read()Label1.Text = dr.Item("dname") ' or dr.Item(0)conn.Dispose() |
将以下 C# 代码添加到按钮的单击事件处理程序中的括号 { 和 } 之间,并确保用您的服务器的主机名称替代 OTNSRVR:
string oradb = "Data Source=( DESCRIPTION=(ADDRESS_LIST=" + "(ADDRESS=(PROTOCOL=TCP)(HOST=OTNSRVR)(PORT=1521)) )" + "(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=ORCL)));" + "User Id=scott;Password=tiger;"; OracleConnection conn = new OracleConnection(oradb); // C#conn.Open();OracleCommand cmd = new OracleCommand(); cmd.Connection = conn;cmd.CommandText = "select dname from dept where deptno = 10"; cmd.CommandType = CommandType.Text;OracleDataReader dr = cmd.ExecuteReader();dr.Read();label1.Text = dr.GetString(0);conn.Dispose(); |
运行应用程序。 单击按钮。 您将看到以下内容:
上机操作 2: 增加交互性
现在在代码中实施了数据库访问的基础,下一步是为应用程序增加交互性。 可以添加一个文本框来接收用户输入的部门号码 (deptno),而不是运行硬编码的查询。
向表单中添加一个文本框控件和另一个标签控件: 将 Label2 控件的文本属性设为 Enter Deptno: 并确保没有将 TextBox1 的 Text 属性设为任何东西。
修改定义选择字符串的代码:
cmd.CommandText = "select dname from dept where deptno = " + TextBox1.Text 'VB.NETcmd.CommandText = "select dname from dept where deptno = " + textBox1.Text; // C#
运行应用程序。在 deptno 输入 10,测试应用程序。 输入一个无效的 deptno,重新测试应用程序。 应用程序将退出。
修改代码以防止在输入无效的 deptno 时出现错误。 让我们回顾一下,ExecuteReader 方法实际返回一个对象。
If dr.Read() Then ' VB.NET Label1.Text = dr.Item("dname")Else Label1.Text = "deptno not found"End Ifif (dr.Read()) // C#{ label1.Text = dr.Item("dname");}Else{ label1.Text = "deptno not found";}
输入不存在的 deptno 数字,测试应用程序。 现在应用程序不再退出。 输入字母 A 代替数字,然后单击按钮。 应用程序退出。 很明显,我们的应用程序需要更好的方法以处理错误。
可能有人会指出,应用程序应当不充许用户进行将导致错误的无效输入,但最终应用程序必须添加强健的错误处理功能。 不是所有的错误都是可预防的,因此必须实施错误处理。
上机操作 3: 利用 DataReader 检索多行和多列
现在检索了单个值,下一步就是利用 DataReader 检索多行和多列。 添加一个 ListBox 控件到表单中,以显示结果。
添加一个 ListBox 控件到表单中。 重新调整控件的大小,以填满表单的大部分宽度。
从查询中删除 where 子句,并添加以下列:
cmd.CommandText = "select deptno, dname, loc from dept" ' VB.NETcmd.CommandText = "select deptno, dname, loc from dept"; // C#
修改 VB.NET 代码,最终结果如下:
Dim oradb As String = "Data Source=(DESCRIPTION=(ADDRESS_LIST=" _ + "(ADDRESS=(PROTOCOL=TCP)(HOST=OTNSRVR)(PORT=1521)) )" _ + "(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=ORCL))); " _ + "User Id=scott;Password=tiger; "Dim conn As New OracleConnection(oradb) ' VB.NETconn.Open( )Dim cmd As New OracleCommandcmd.Connection = conncmd.CommandText = "select deptno, dname, loc from dept" cmd.CommandType = CommandType.TextDim dr As OracleDataReader = cmd.ExecuteReader()While dr.Read() ListBox1.Items.Add( "The " + dr.Item(1) + _" department is in " + dr.Item("loc"))End Whileconn.Dispose() |
string oradb = "Data Source=(DESCRIPTION= (ADDRESS_LIST=" + "(ADDRESS=(PROTOCOL=TCP)(HOST=OTNSRVR)(PORT=1521)))" + "(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=ORCL)));" + "User Id=scott;Password=tiger;";OracleConnection conn = new OracleConnection(oradb); // C#conn.Open();OracleCommand cmd = new OracleCommand();cmd.Connection = conn; cmd.CommandText = "select dname from dept where deptno = 10"; cmd.CommandType = CommandType.Text; OracleDataReader dr = cmd.ExecuteReader();while (dr.Read()) { ListBox1.Items.Add("The " + dr.Item(1) + " department is in " + dr.GetString(0));}conn.Dispose(); |
- 上一篇:Oracle数据库配置错误信息解决方法
- 下一篇:Oracle应用服务器10g
精彩图集
精彩文章



