Click here to Skip to main content
15,884,353 members
Articles / Programming Languages / Visual Basic

Gotcha #1161: Using Named Parameters with Oracle ODP.NET

Rate me:
Please Sign up or sign in to vote.
4.89/5 (25 votes)
8 Jun 2011CPOL1 min read 90.9K   14   14
Using Named Parameters with Oracle ODP.NET

Introduction

After being legged-up for a good couple of hours by this the other day, I'm writing this quick note to try and prevent other people from nearly throwing their PC out of the window in frustration. It concerns using named query parameters with the Oracle Data Provider for .NET (ODP.NET).

The Problem

Consider the following simple data-retrieval operation:

C#
// C#
using (OracleConnection connection = new OracleConnection
	(ConfigurationManager.ConnectionStrings["OracleExpress"].ConnectionString))
{
    string query = "SELECT SOME_COLUMN, ANOTHER_COLUMN, THIRD_COLUMN FROM SOME_TABLE 
		WHERE ANOTHER_COLUMN = :SomeParam AND THIRD_COLUMN = :AnotherParam";
    OracleCommand command = new OracleCommand(query, connection) 
			{ CommandType = CommandType.Text };
    command.Parameters.Add(":AnotherParam", OracleDbType.Varchar2).Value = "Ping";
    command.Parameters.Add(":SomeParam", OracleDbType.Varchar2).Value = "Foo";
    connection.Open();
    IDataReader reader = command.ExecuteReader();
    while (reader.Read())
    {
        int someColumn = reader.GetInt32(reader.GetOrdinal("SOME_COLUMN"));
        string anotherColumn = reader.GetString(reader.GetOrdinal("ANOTHER_COLUMN"));
        string thirdColumn = reader.GetString(reader.GetOrdinal("THIRD_COLUMN"));
        Console.WriteLine(String.Format("{0}: {1}, {2}", someColumn, 
		anotherColumn, thirdColumn));
    }
}
VB.NET
' Visual Basic
Using connection As OracleConnection = New OracleConnection_
	(ConfigurationManager.ConnectionStrings("OracleExpress").ConnectionString)
    Dim query As String = "SELECT SOME_COLUMN, ANOTHER_COLUMN, _
	THIRD_COLUMN FROM SOME_TABLE WHERE ANOTHER_COLUMN = _
	:SomeParam AND THIRD_COLUMN = :AnotherParam"
    Dim command As OracleCommand = New OracleCommand(query, connection) _
	With {.CommandType = CommandType.Text}
    command.Parameters.Add(":AnotherParam", OracleDbType.Varchar2).Value = "Ping"
    command.Parameters.Add(":SomeParam", OracleDbType.Varchar2).Value = "Foo"
    connection.Open()
    Dim reader As IDataReader = command.ExecuteReader()
    While reader.Read()
        Dim someColumn As Integer = reader.GetInt32(reader.GetOrdinal("SOME_COLUMN"))
        Dim anotherColumn As String = _
		reader.GetString(reader.GetOrdinal("ANOTHER_COLUMN"))
        Dim thirdColumn As String = reader.GetString(reader.GetOrdinal("THIRD_COLUMN"))
        Console.WriteLine(String.Format("{0}: {1}, {2}", someColumn, _
	anotherColumn, thirdColumn))
    End While
End Using

Now, assuming that the data in our table is as follows:

SOME_COLUMNANOTHER_COLUMNTHIRD_COLUMN
1FooPing
2BarPong
3BazPing

We should get back a single row from the database, right? Wrong! Actually what we get back is nothing. Why is this? If we run this query in another tool of our choice (SQL+, TOAD, etc.), we find it works as expected.

The Solution

After some scouring of Google, I eventually tracked down what was causing the problem. It turns out that unlike, for example the SQL-Server data provider, the Oracle data provider always binds parameters by position unless told otherwise. So, even though we have named parameters in our query, and we have added named parameters to the OracleCommand object, the data provider still binds the parameters by position; and as we have added the parameters in the 'wrong' order (albeit deliberately in this example) the query doesn't throw an exception, it merely returns an empty result set as the query received by the database is the equivalent of:

SQL
SELECT SOME_COLUMN, ANOTHER_COLUMN, THIRD_COLUMN
FROM SOME_TABLE
WHERE ANOTHER_COLUMN = 'Ping'
AND THIRD_COLUMN = 'Foo'

The solution: This isn't made entirely clear on the Oracle documentation, but there is an additional property, BindByName, on the OracleCommand object, which must be set to true in order to bind parameters by name:

C#
// C#
OracleCommand command = new OracleCommand(query, connection) 
	{ CommandType = CommandType.Text, BindByName = true };
VB.NET
' Visual Basic
Dim command As OracleCommand = New OracleCommand(query, connection) _
	With {.CommandType = CommandType.Text, .BindByName = True}

The above query should now work as expected.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionVery Useful! Pin
GregScott3337-Feb-18 0:52
GregScott3337-Feb-18 0:52 
QuestionThx! Pin
Paul Sincai9-Oct-17 1:14
Paul Sincai9-Oct-17 1:14 
GeneralThank you ! Pin
NewAlex20168-Apr-16 7:33
NewAlex20168-Apr-16 7:33 
QuestionThank you very much Pin
Amit Das Celtic19-May-14 0:54
Amit Das Celtic19-May-14 0:54 
AnswerRe: Thank you very much Pin
minek7328-May-14 0:40
minek7328-May-14 0:40 
QuestionMany thanks Pin
Shashidhar Rao Nellutla28-Nov-13 6:12
Shashidhar Rao Nellutla28-Nov-13 6:12 
QuestionThis article saved my PC Pin
Member 98527419-Oct-13 5:52
Member 98527419-Oct-13 5:52 
..after 8h of frustration i was going to throw away my PC


thank you thank you....
QuestionThank you thank you thank you thank you! Pin
Marcos Foster18-Apr-13 4:29
Marcos Foster18-Apr-13 4:29 
QuestionThanks Pin
wickedtuner24-Mar-13 22:38
wickedtuner24-Mar-13 22:38 
GeneralMy vote of 5 Pin
Michael Latham5-Sep-12 7:29
Michael Latham5-Sep-12 7:29 
QuestionSaved me hours of fustration! Pin
RJustesen29-Nov-11 6:22
RJustesen29-Nov-11 6:22 
GeneralMy vote of 5 Pin
johnbrown1053-Nov-11 22:11
johnbrown1053-Nov-11 22:11 
GeneralMy vote of 5 Pin
Dieter Buecherl13-Jun-11 21:01
Dieter Buecherl13-Jun-11 21:01 
GeneralMy vote of 5 Pin
OrbitalInMotion9-Jun-11 10:50
OrbitalInMotion9-Jun-11 10:50 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.