Developer: .

NET

Build a .NET Application on the Oracle Database for Visual Studio .NET 2003
by John Paul Cook

TAGS dotnet, database, All

Learn the basic yet essential processes involved in building a .NET application that uses an Oracle database. Updated September 2008 Read the Oracle Database 11g/Visual Studio .NET 2005 or 2008 version of this guide With the rising popularity of Microsoft's .NET Framework, many developers are hungry for information about the best means of integrating .NET applications with Oracle—not only in terms of basic connectivity, but also in relationship to effective and efficient application development using Visual Studio.NET (VS.NET). In this article, I'll explain the basic yet essential processes involved in building a .NET application that uses an Oracle database, including:

  

How to add project references to support Oracle class libraries in your .NET project How to create Oracle Database connection strings How to work with Connection, Command, and DataReader objects

You will have the opportunity to apply what you have learned in three practice labs, ranging in difficulty from the relatively simple to the more complex. For information and labs about how to secure your application, see my article " Securing a .NET Application on the Oracle Database." (Also, see the OTN .NET Developer Center for technical articles covering a range of Oracle .NET application lifecycle issues.) Note that the free Oracle Developer Tools for Visual Studio, available for download from OTN, provides a Visual Studio add-in that makes the development of .NET apps on Oracle much easier and more intuitive. That subject is beyond our scope here, however; see the Oracle Developer Tools for Visual Studio Product Center for more information. .NET Data Provider In addition to basic Oracle client connectivity software, .NET applications require the use of what is known as a managed data provider (where "managed" refers to code managed by the .NET framework). The data provider is the layer between the .NET application code and the Oracle client connectivity software. In almost every case, the best performance is achieved by using a provider optimized for a specific database platform instead of the generic .NET OLE DB data provider. Oracle, Microsoft, and third-party vendors all offer .NET data providers optimized for Oracle. Oracle and Microsoft make their Oracle data providers available for free. (Microsoft's provider for the .NET Framework 1.1 is included in the framework, but it still requires Oracle client software installation.) In this article, we will use of the Oracle Data Provider for .NET (ODP.NET), which is included with the Oracle Database or as a separate download. ODP.NET provides standard ADO.NET data access, while exposing Oracle database-specific features, such as XML DB, data access performance optimizations, and Real Application Clusters connection pooling.

When ODP.NET and Oracle client software are installed, application development using Visual Studio can begin. It's a good idea to confirm client connectivity before starting development. If you can connect to Oracle using Oracle client software such as SQL*Plus on the same machine as Visual Studio, then you know that your Oracle client-side software is properly installed and configured. If you are new to Oracle, see the section "Installing .NET Products" in the Oracle Database 2 Day Developer's Guide for background information regarding installing and configuring ODP.NET specifically, or to the Oracle Database Documentation Library for general information about the Oracle Database. Creating a Project in Visual Studio.NET After starting VS.NET, the first task is to create a project. You can either click the New Project button or select File | New | Project... as shown below.

Figure 1: Creating a new project in Visual Studio.NET A New Project dialog box appears. On the left side of the dialog box under Project Types , select the programming language of your choice. In our example, VB.NET was chosen. On the right side under Templates , choose a project template. To keep things simple, a Windows Application is selected here.

many people use the same name for both. right click and select Add Reference.Figure 2: Using the New Project dialog You'll want to specify meaningful names for the project name (we used OraWinApp) and the solution name (we used OraSamples). Adding a Reference Because our project must connect to an Oracle database. . select the References node. Alternatively. Within the Solution Explorer. it is necessary to add a reference to the dll containing the data provider of our choice. A solution contains one or more projects. When a solution contains only one project. you can go to the menu bar and select Project and then select Add Reference .

Figure 3: Adding a reference The Add Reference dialog box appears. .

Figure 5: Solution Explorer after selecting the . and finally click the OK button to make the ODP.Figure 4: Selecting the ODP.dll from the list. then click the S elect button.DataAccess.NET Managed Data Provider Select the Oracle.NET data provider known to your project.

Password=tiger. it is standard practice to add VB. these statements appear at or near the top of a code file.DataAccess. or J# import statements." _ + "User Id=scott.Client.ora file.NET Dim oradb As String = "Data Source=(DESCRIPTION=" _ + "(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=OTNSRVR)(PORT=1521)))" _ + "(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=ORCL))). Intellisense will help you complete the addition of an Imports or using statement.Password=tiger. you would use the following syntax: Dim oradb As String = "Data Source=OraDb. // J#ODP. Simply replace the name of the alias with how it would be defined in a tnsnames. However. By convention. Imports Oracle. the clear text approach is undesirable from a security . before the namespace or class declaration. // C# You can modify the connection string to obviate the need for the tnsnames. Connection Strings and Objects An Oracle connection string is inseparable from Oracle names resolution.User Id=scott. fully qualified names.". however.DataAccess." + "User Id=scott. To use the OraDb alias defined in the tnsnames.NET Imports statements. the username and password are embedded in the connection string in clear text.Password=tiger. ' VB.ora file as follows: OraDb= (DESCRIPTION= (ADDRESS_LIST= (ADDRESS=(PROTOCOL=TCP)(HOST=OTNSRVR)(PORT=1521)) ) (CONNECT_DATA= (SERVER=DEDICATED) (SERVICE_NAME=ORCL) ) ) The OraDb alias defines the database address connection information for the client." ' VB.NET string oradb = "Data Source=OraDb.DataAccess.".NET using Oracle." // C# string oradb = "Data Source=(DESCRIPTION=" + "(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=ORASRVR)(PORT=1521)))" + "(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=ORCL))). This is the simplest approach to creating a connection string. Technically these statements are not required but they do allow you to refer to database objects without using lengthy.ora file. As you can see above.NET/C# Statements After adding references.Password=tiger.Oracle Managed Provider VB.Client.User Id=scott.ora file shown above.Client ' VB. Suppose we had a database alias of OraDb defined in a tnsnames. // C# import Oracle. C# using statements.NET Oracle managed provider If you added the reference.

Item(0) ' retrieve the first column in the select list dr. // C# OracleCommand cmd = new OracleCommand(sql. all of which are available in C#. Dim conn As New OracleConnection(oradb) ' VB.NET OracleConnection conn = new OracleConnection(oradb).ConnectionString = oradb. The connection string must be associated with the connection object. conn.NET Dim cmd As New OracleCommand(sql. the syntax can be structured slightly differently.Text. Zero-based ordinals are passed to the .NET language. which is overloaded. ODP.NET DLL and EXE files and view the original clear text contents.Text = = = = dr. // C# conn. use the Open method to make the actual connection. Command Object The Command object is used to specify the SQL command text that is executed. Returned data is accessible by passing either the column name or zero-based column ordinal to the OracleDataReader. you must understand that compiled . Visual Basic. // C# We'll cover error handling later.ConnectionString = oradb OracleConnection conn = new OracleConnection().NET conn. The Command object has methods for executing the command text. Dim sql As String = "select dname from dept where deptno = 10" ' VB.Read() Label1.GetString(0) ' return a .GetOracleString(0) ' return an Oracle data type There are typed accessors for returning . Dim dr As OracleDataReader = cmd.Open() ' VB. Retrieving a Scalar Value Retrieving data from the database can be accomplished by instantiating an OracleDataReader object and using the ExecuteReader method.) Next. After associating a connection string with a connection object.perspective. (Encryption is in fact the appropriate solution.NET will perform a SQL query to return the department name (DNAME) from the departments table (DEPT) where the department number (DEPTNO) is 10. it must be instantiated from its class and it has an overloaded constructor. conn) cmd.NET application code is only marginally more secure than the clear text source code files.Item("dname") ' retrieve by column name dr. you must instantiate a connection object from the connection class. Different methods are appropriate for different types of SQL commands. It is very easy to decompile .Text string sql = "select dname from dept where deptno = 10". conn). // C# Notice that the connection string is associated with the connection object by being passed through the object's constructor. In this sample. The constructor's other overload allows the following alternative syntax: Dim conn As New OracleConnection() ' VB.Text Label1.NET data type dr.NET native data types and others for returning native Oracle data types.Text Label1. either a SQL string or a stored procedure. Using different overloads.Open().CommandType = CommandType. Similar to the Connection object.NET conn. cmd.CommandType = CommandType. but that subject would be a quite lengthy digression from our discussion here. which returns an OracleDataReader object.ExecuteReader() ' Visual Basic dr.Text Label1. or any other . In particular.

Read(). label1. dr. // C# dr. it's still better to use explicit data type conversions instead of implicit data type conversion. An explicit cast to integer is shown below: Label1. Error Handling When an error occurs.ToString(). . You'll find yourself doing explicit conversions: label1. } In addition.GetInt16("deptno").GetString(0). // C# retrieve by column name label1.Item("deptno")) ' Visual Basic integer to string cast C# is not as forgiving as Visual Basic on implicit conversions. But even when it works. which is especially important under high load conditions. cmd. // return a . label1. C# offers a special syntax that automatically disposes a connection when it goes out of scope.accessors to specify which column to return. which is not a string. OracleCommand includes a Dispose method.Dispose(). The Dispose method calls the Close method. // return an Oracle data type In this simplified example. OracleCommand cmd = new OracleCommand().GetString(0). The using keyword enables this feature. cmd.Open(). Closing and disposing .Text = dr.ToString(). You can experiment with some of the concepts we've learned here in Lab 1 (Retrieving Data from the Database) and Lab 2 (Adding Interactivity).NET objects free up system resources.CommandType = CommandType.CommandText = "select dname from dept where deptno = 10".Text = CStr(dr. OracleDataReader includes a Close and Dispose method. the returned value of DNAME is a string and is used to set the value of the label control's text property.Text = dr["dname"].ToString().ExecuteReader(). OracleDataReader dr = cmd. The .NET applications should gracefully handle the error and inform the user with a meaningful .Text = dr. Close and Dispose Either the connection object's Close or the Dispose method should be called to close the connection to the database when the connection is no longer needed. which is also a string. there would be a data type mismatch.Connection = conn. conn. had been retrieved instead. // C# You can explicitly cast scalar values as well as arrays. // C# Alternatively. ensuring more efficient application performance.Read(). using (OracleConnection conn = new OracleConnection(oradb)) { conn.NET runtime attempts to implicitly convert from one data type to another when the source and destination data types don't match.Close() ' Visual Basic conn.Dispose() ' Visual Basic conn. But if DEPTNO.ToString().NET data type label1. OracleDataReader dr = cmd. throwing an exception.Close(). cmd.Text = dr. // C# conn.Text = dr.Text. Sometimes the data types are incompatible and the implicit conversion fails.GetOracleString(0).ExecuteReader().

cmd.Open(). } Although this approach will gracefully capture any errors in attempting to get data from the database. OracleCommand cmd = new OracleCommand().ToString()).Connection = conn.ToString() } } catch (Exception ex) // catches any error { MessageBox. cmd.CommandText = "select dname from dept where deptno = " + TextBox1. } finally { // In a real application.Read() Then Label1. For example.message. Here is a relatively minimalist example of using the Try-Catch-Finally syntax: ' Visual Basic Try conn.Text cmd.Item(0) End If Catch ex As Exception ' catches any error MessageBox.CommandType = CommandType.Message.ToString()) Finally ' In a real application. put cleanup code here.NET languages. if (dr.Text If dr.Connection = conn cmd.Show(ex.Item("dname") ' or use dr. look at the following message displayed when the database is unavailable: .ToString(). cmd.GetOracleString(0).Text.Show(ex.Open() Dim cmd As New OracleCommand cmd.Message.CommandType = CommandType.Text = dr.Text. // or use dr.Text = dr["dname"]. End Try // C# try { conn. it is not user friendly.Read()) // C# { label1. put cleanup code here.CommandText = "select dname from dept where deptno = " + textBox1. Try-Catch-Finally structured error handling is a part of .

Show("Database error: " + ex. the first Catch statement branch is skipped. If there aren't any Oracle errors to catch.Number) { case 1: MessageBox.").Message.Show(ex.") Case 12545 MessageBox. break.Show("The database is unavailable. An ORA-12545 is quite meaningful for an Oracle DBA or developer.Show("Error attempting to insert duplicate data. } } catch (Exception ex) // catches any error { MessageBox.Show("Error attempting to insert duplicate data. Catch ex As OracleException ' catches only Oracle errors Select Case ex.Message. but not for an end user.ToString()) catch (OracleException ex) // catches only Oracle errors { switch (ex.") Case Else MessageBox."). After implementing the userfriendly exception handling code.ToString()) End Select Catch ex As Exception ' catches any error MessageBox. case 12545: MessageBox. break. Catch statements must be ordered in the code from most specific to most general. the ORA-12545 error message appears as follows: . default: MessageBox. A better solution is to add an additional Catch statement to trap for the most common database errors and provide user-friendly messages. } Notice the two Catch statements in the code sample above.Show("The database is unavailable.Number Case 1 MessageBox.Message.Show(ex.Show("Database error: " + ex.ToString()).ToString()). break. leaving any other type non-Oracle error to be caught by the second Catch statement.Message.Figure 6: An ORA-12545 error caught and displayed to the user.

as the following code snippet illustrates: While dr.Item("loc")) End While while (dr.NET.Item("loc"). An OracleDataReader is compatible with a ListBox control.Read() ' Visual Basic ListBox1. Oracle. dname. An OracleDataReader can retrieve values for multiple columns and multiple rows. John Paul Cook ( johnpaulcook@email.Text = "The " + dr["dname"].Items. Ordinals are relative to the order in the query. the LOC column's value can be retrieved in Visual Basic by using either dr.NET consultant based in Houston. An OracleDataReader is a forward-only. dname.NET. He is the author of numerous articles on . so it can't be bound to an updateable or fully scrollable control such as a Windows Forms DataGrid control. Here is a code snippet that concatenates the DNAME and LOC columns from the previous query: Label1.NET programming languages.ToString() + " department is in " + dr["loc"]. First consider a multiple column. You should now have the capability to connect to the database and retrieve multiple columns and rows.Item("loc") ' VB label1. either zero-based ordinals or column names can be used. single row query: select deptno.Figure 7: A user-friendly error message for an ORA-12545 error The Finally code block is always executed regardless of whether or not an error occurred.Item("dname") + " department is in " + dr. He is an Oracle certified DBA and a Microsoft MCSD for . and other topics and has been developing relational database applications since 1986.ToString(). If you don't use Using or using. a control that can display multiple rows is desirable.Add("The " + dr["dname"].ToString()).ToString() + " department is in " + dr["loc"].Item(2) or dr. read-only cursor. } Lab 3 (Retrieve Multiple Columns and Rows with an OracleDataReader) highlights some of these concepts.Item("dname") + " department is in " + dr. you should dispose your connection and other objects in the Finally code block. His current interests include Visual Studio 2005 and Oracle 10g. // C# Now consider a query that returns multiple rows: select deptno. loc from dept To process multiple rows returned from an OracleDataReader.Text = "The " + dr. loc from dept where deptno = 10 To obtain the values of the columns. It is where cleanup code belongs.Add("The " + dr.Read()) // C# { listBox1. Lab 1: Retrieving Data from the Database . Summary This article has introduced you to the process of accessing Oracle databases using VS. Furthermore. Retrieving Multiple Values Using a DataReader So far our examples have only showed how to retrieve a single value.Items. Thus. some type of looping construct is needed.com) is a database and .

Add code to retrieve data from the Oracle database and display the results on the form.1. 2. Be sure to leave room above the controls to allow additions that will be made in Lab 2. Put the code in a click event handler for the button. We begin with the requirement that you've created a project and added a reference as shown previously in this article. The easiest way to get started with this task is to double click the button because it will create a stub for the event handler. Begin by adding a button control and a label control to the Windows form. Figure 8: Lab 1 form with button and label controls 3. .

Add VB.DataAccess. 6.NET 18. 4. Dim conn As New OracleConnection(oradb) ' VB.NET Imports statements before the Public Class declaration or C# using statements before the namespace declaration. Add the VB. + "(ADDRESS=(PROTOCOL=TCP)(HOST=OSRVR)(PORT=1521)))" _ 14. using System.NET 7.NET version of the click event handler code between the Private Sub and End Sub statements (be sure to replace OTNSRVR with your server's host name):: 12.Data ' VB. 5. // C# 10. + "User Id=scott. 20.NET Oracle managed provider 8. + "(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=ORCL))).Client.DataAccess. 17.Client ' ODP." 16. Dim cmd As New OracleCommand .Figure 9: Click event handler stub.Open() 19. Dim oradb As String = "Data Source=(DESCRIPTION=(ADDRESS_LIST=" _ 13. using Oracle. Imports Oracle.Password=tiger. Imports System." _ 15.NET Oracle managed provider 11.Data. 9. // ODP. conn.

CommandType = CommandType. 46. string oradb = "Data Source=(DESCRIPTION=(ADDRESS_LIST=" 34.CommandType = CommandType.Connection = conn cmd. You should see the following: . 25.Dispose() 32. 44. + "(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=ORCL))).Item(0). 27. 43. 45.Read() ' replace this statement in next lab Label1.Text. 53.Text = dr. cmd. 30. // replace this statement in next lab 48.Text Dim dr As OracleDataReader = cmd. cmd.Open(). 37. 52.Password=tiger. Add the following C# code to the click event handler between the { and } curly braces for the button's click event handler (be sure to replace OTNSRVR with your server's host name): 33.Dispose(). 42.Dispose() conn. 38. 28. 50.Dispose() cmd. 24. 41. OracleCommand cmd = new OracleCommand()." 36. conn.CommandText = "select dname from dept where deptno = 10" cmd. Run the application. 22. + "(ADDRESS=(PROTOCOL=TCP)(HOST=ORASRVR)(PORT=1521)))" 35. 23. Click the button. // C# 39. cmd. 40. label1. dr. 29.".Connection = conn. 31. 47.ExecuteReader().Item("dname") ' or dr. dr.ExecuteReader() dr.21. 51. remove in next lab dr.Read(). 26.Text = dr["dname"].ToString().Dispose(). OracleDataReader dr = cmd. + "User Id=scott. conn. // remove in next lab 49.Dispose().CommandText = "select dname from dept where deptno = 10". cmd. cmd. OracleConnection conn = new OracleConnection(oradb).

Instead of running the hard coded query.Figure 10: Data successfully retrieved 54.. 1. . DEPTNO). Set the text property of the Label2 control to Enter DEPTNO: and make sure that the Text property of TextBox1 isn't set to anything. a textbox control can be added to accept a user input for the department number (i. Lab 2: Adding Interactivity Now that the basics of database access are implemented in the code. Add a textbox control and another label control to the form as shown below.e. the next step is to add interactivity to the application.

The application will abort. cmd. Retest the application by entering an invalid DEPTNO (e. cmd.Text 'VB. .CommandText = "select dname from dept where deptno = " + textBox1.CommandText = "select dname from dept where deptno = " + TextBox1.Figure 11: Lab 2 form with button and label controls. 3.. Run the application. Modify the code that defines the select string: 4.NET 5.g.Text. // C# 7. 6. Test the application by entering 10 for the deptno. 2. 50).

Text = dr["dname"].Read() Then ' Visual Basic Label1. 13. Enter the letter A instead of a number and click the button. 21. If dr. The application aborts.Text = dr.Item("dname"). 11. 23. Replace the line containing dr.ToString().ToString() Else Label1.. 19. 24. Now the application no longer aborts.Read with all of the following statements. Modify your code to prevent an error when an invalid DEPTNO is entered.Read()) // C# { label1. } 25. 18.Figure 12: An unhandled exception 8. Test the application by entering a DEPTNO that does not exist. 22. our . 9.Text = "deptno not found". 15. 16. 10. 14. } else { label1. 17. 12. Clearly. 20.Text = "deptno not found" End If if (dr. Recall that the ExecuteReader method actually returns an object.

Modify your VB. Figure 13: Form with ListBox added 2. Remove the where clause from the query and add the additional columns: 4. Lab 3: Retrieve Multiple Columns and Rows with a DataReader Now that a single value has been retrieved. 3. A ListBox control is added to the form to display the results. Not all errors are preventable. cmd. cmd.application needs a better approach to handling errors. ultimately the application must have robust error handling added.NET 5. dname.CommandText = "select deptno. Resize the control to fill most of the width of the form as shown below.CommandText = "select deptno. 6. 1. loc from dept".NET . // C# 7. loc from dept" ' VB. The query results will be read in a while loop and will populate the ListBox control. Add a ListBox control to the form. dname. Although it could be argued that the application should not allow the user to make invalid inputs that would cause an error. so error handling must be implemented. the next step is to retrieve multiple columns and rows with a DataReader.

code to look like this: 8.CommandText = "select deptno.Password=tiger. ListBox1.Dispose()." + "User Id=scott.Add("The " + dr. dr.ToString()).Read() 23. cmd.Connection = conn 18.Open(). 16. Dim cmd As New OracleCommand 17." _ 11. " department is in " + dr. OracleConnection conn = new OracleConnection(oradb).Dispose(). The ListBox should be populated with all of the department names and locations . conn.Items. 13.Dispose() 28. OracleCommand cmd = new OracleCommand(). cmd. + "(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=ORCL))).CommandType = CommandType. 27. 21.Items." 12.Dispose() 29. cmd.Password=tiger. cmd. Dim dr As OracleDataReader = cmd. + "(ADDRESS=(PROTOCOL=TCP)(HOST=OTNSRVR)(PORT=1521)))" _ 10. loc from dept". OracleDataReader dr = cmd. cmd. conn. while (dr.Dispose(). Dim oradb As String = "Data Source=(DESCRIPTION=(ADDRESS_LIST=" _ 9. dname.Read()) { listBox1.". End While 26.ExecuteReader() 22. dname.Text.Item("loc")) 25.Open() 15. conn. 30.CommandText = "select deptno.Item("dname") + _ 24. 19. cmd. cmd.CommandType = CommandType. } dr. loc from dept". + "User Id=scott.Text 20.Add("The " + dr["dname"]. // C# conn. While dr.Connection = conn. cmd. Dim conn As New OracleConnection(oradb) ' Visual Basic 14.ToString() + " department is in " + dr["loc"].ExecuteReader().Dispose() Modify your C# code to look like this: string oradb = "Data Source=(DESCRIPTION=(ADDRESS_LIST=" + "(ADDRESS=(PROTOCOL=TCP)(HOST=ORASRVR)(PORT=1521)))" + "(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=ORCL))). Run the application.

.from the DEPT table. The code downloads have error handling implemented.

Sign up to vote on this title
UsefulNot useful