ghigad ghigad - 1 year ago 182
C# Question

Binding Guid parameter in Oracle ADO.NET

I have a C# application (.NET framework 4.0) that accesses an Oracle Database using the Oracle.DataAccess.dll provider from Oracle using an Instant Client (v. 11.2.0.1).

My table has 2 columns: Id (type RAW) and Name (type VARCHAR2).

I can run a SELECT and bind the Id parameter properly. However, when I try exactly the same kind of binding in an Update, the row is never updated.

Here is a sample program to demonstrate my problem.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using Oracle.DataAccess.Client;
using System.Configuration;
using System.Data;
using System.Data.Common;
using System.Transactions;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string connectString = ConfigurationManager.ConnectionStrings["testOracle"].ConnectionString;
Guid id = Guid.Parse("590704389D204D979A8BA775F000F300");

using (OracleConnection connection = new OracleConnection(connectString))
{
connection.Open();

using (OracleCommand command = connection.CreateCommand())
{
command.CommandType = CommandType.Text;
command.CommandText = "SELECT Id, Name FROM Enterprise WHERE Id = :Id";

command.Parameters.Add(":Id", id.ToString("N").ToUpper());

using (OracleDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Trace.WriteLine(string.Format("ID: {0}, Name: {1}",
new Guid((byte[])reader["Id"]),
reader["Name"]));
}
}
}

using (OracleCommand command = connection.CreateCommand())
{
command.CommandType = CommandType.Text;
command.CommandText = "UPDATE Enterprise SET Name = :Name WHERE Id = :Id";

command.Parameters.Add(":Id", id.ToString("N").ToUpper());
command.Parameters.Add(":Name", "xxxx");

Trace.WriteLine(string.Format("Rows affected: {0}", command.ExecuteNonQuery()));
}

using (OracleCommand command = connection.CreateCommand())
{
command.CommandType = CommandType.Text;
command.CommandText = "SELECT Id, Name FROM Enterprise WHERE Id = :Id";

command.Parameters.Add(":Id", id.ToString("N").ToUpper());

using (OracleDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Trace.WriteLine(string.Format("ID: {0}, Name: {1}",
new Guid((byte[])reader["Id"]),
reader["Name"]));
}
}
}
}
}
}
}


My program always outputs:

ID: 38040759-209d-974d-9a8b-a775f000f300, Name: bbbbb
Rows affected: 0
ID: 38040759-209d-974d-9a8b-a775f000f300, Name: bbbbb


I also tried the following statement, but it still fails

UPDATE Enterprise SET Name = :Name WHERE rowid = (SELECT rowid FROM Enterprise WHERE Id = :Id)


How can I bind my Id parameter so that my Update starts working?

Answer Source

I finally figured it out.

It turns out that Oracle's default behavior is to bind the parameters in the order they were defined in the query.

So to make my sample program work, I have two solutions.

1 - Switch the order of parameter binding

Change

command.CommandType = CommandType.Text;
command.CommandText = "UPDATE Enterprise SET Name = :Name WHERE Id = :Id";

command.Parameters.Add(":Name", "toto");
command.Parameters.Add(":Id", id.ToString("N").ToUpper());

To

command.CommandType = CommandType.Text;
command.CommandText = "UPDATE Enterprise SET Name = :Name WHERE Id = :Id";

command.Parameters.Add(":Id", id.ToString("N").ToUpper());
command.Parameters.Add(":Name", "toto");

2 - Use BindByName

Set the BindByName property to true.

command.CommandType = CommandType.Text;
command.BindByName = true;
command.CommandText = "UPDATE Enterprise SET Name = :Name WHERE Id = :Id";

command.Parameters.Add(":Id", id.ToString("N").ToUpper());
command.Parameters.Add(":Name", "toto");
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download