how to create IDbDataParameter with null-able value? - c#

I have add a null value to parameter list for inserting values to a table, which accepts some null values. Here is my example codes:
bool sql = true;
// ....
List<IDbDataParameter> parameters = new List<IDbDataParmeter>();
// adding values...
object objVal = 1;
parameters.Add(
sql ? new SqlParameter("#colIntA", objVal) :
new OracleParamer(":colIntA", objVal));
// this would not work, what should I add?
objVal = string.Empty;
parameters.Add(
sql ? new SqlParameter("#colIntB", objVal) :
new OracleParamer(":colIntB", objVal));
Not sure if I have use db specific DbNull value and is that also SQL or Oracle specific?

You're trying to assign an empty string ('') to an int parameter there, so yeah, that's not going to work.
To represent a database-independent null value, use DbNull.Value.
new SqlParameter("colIntB", DbNull.Value)
(Note that I've left off the "#", which works in my experience with Sqlparameters. I'm not sure whether you can do the same with the ":" for Oracle.)
One extra tip: Use your connection to create the command, and the command to create the parameters. That will create instances of the right class depending on the type of the underlying connection:
IDbConnection conn = sql ? new SqlConnection(...) : new OracleConnection(...);
// this will give you either an SqlCommand or an OracleCommand
IDbCommand cmd = conn.CreateCommand();
// this will give you either an SqlParameter or an OracleParameter
IDbDataParameter param1 = cmd.CreateParameter();
param1.ParameterName = "colIntB";
param1.Value = objVal;
cmd.Parameters.Add(param1);

Use DbNull.Value. That will work for any ADO.NET-compatible data source (both SQL and Oracle providers), as it is the responsibility of the provider to know what to do when it encounters a DbNull value.

Related

Conversion failed when converting from string to uniqueidentifier - loading DataTable with ExecuteReader

In attempting to do a SQL query (which returns one string and one uniqueidentifier to columns 0 and 1 respectively) I get "Conversion failed when converting from a character string to uniqueidentifier" in my exceptions log. How can I avoid this? I'm assuming the issue is, the datatables columns are not defined, so it's expecting a string and SQL is trying to convert it. The exception is logged. Surprisingly to me the GUID is stored successfully to da[1]. So my program technically works, however I want to clear this exception and to do that I need to understand why it's happening and how to go about fixing it.
da = new DataTable();
da.Clear();
...
string invoiceStatusSQL = #"select status,invoice_id from invoices where acct_id='" + accountid + "'";
command = new SqlCommand(invoiceStatusSQL, cnn);
da.Load(command.ExecuteReader());
You should always parameterise your SQL queries to help prevent SQL injection and avoid problems like you're facing now. See Why do we always prefer using parameters in SQL statements?.
Use SqlParameter to add the parameters to the SqlCommand.
string invoiceStatusSQL = #"select status, invoice_id from invoices where acct_id = #accountId";
command = new SqlCommand(invoiceStatusSQL, cnn);
SqlParameter idParam = new SqlParameter("#accountId", accountid);
command.Parameters.Add(idParam);
da.Load(command.ExecuteReader());
You can also specify the actual database type when creating the parameter, which will reduce any issues you might have with the framework inferring the type incorrectly (although I don't think that would happen in your case for a Guid/UniqueIdentifier). One way to specify the type is shown below.
var p = new SqlParameter
{
ParameterName = "#accountId",
SqlDbType = SqlDbType.UniqueIdentifier,
Value = accountid
};

Oracle ASCII Database with C# Unicode Bind Variables Not Working - ODP.NET

We have a US7ASCII 11gr2 database that I'm trying to build parameterised queries against.
public CustDetailsModel SelectCustDetails(string CustCode)
{
string sql;
OracleDataReader reader;
OracleConnection OraConn = OraConnection.GetConnection;
OraConn.Open();
sql = "SELECT CUSTOMER, NAME, POSTCODE FROM CUSTOMER WHERE CUSTOMER = :CUSTCODE";
OracleCommand cmd = new OracleCommand(sql, OraConn);
OracleParameter parameter = cmd.CreateParameter();
parameter.ParameterName = "CUSTCODE";
parameter.OracleDbType = OracleDbType.NVarchar2;
parameter.Value = CustCode;
cmd.Parameters.Add(parameter);
reader = cmd.ExecuteReader();
reader.Read();
return new CustDetailsModel
{
Cust = reader.GetString(reader.GetOrdinal("CUSTOMER")),
CustName = reader.GetString(reader.GetOrdinal("NAME")),
CustPostCode = reader.GetString(reader.GetOrdinal("POSTCODE")),
};
}
At the add parameter line, the above code triggers a System.InvalidCastException "Unable to cast object of type 'System.String' to type 'Oracle.ManagedDataAccess.Client.OracleParameter".
I've tried everything I can find on the internet including stringbuilder, bind by name, different dbtypes etc.
Does anybody know how to set up a string bind variable in C# to query against an ASCII oracle db?
Thanks in advance.
EDIT
I should explain that I know it is something to do with the disparate types of the db and application because we have successfully used int bind variables and, we can also replace the string bind variables with hardcoded values. We can also replace string bind variables with regular string variables (which we're trying to avoid). It seems to be an issue with the conversion of the bind variable when it hits the database?

C#: Creating SQLParameter at runtime

I'm curious if it's possible to create a SQLParameter in runtime and add it to SQLCommand or not.
What I'm trying to do is:
public void addParameters(string paramName, paramType, SqlParameter paramCommand)
{
SqlParameter myParameter = new SqlParameter("#" + paramName, paramType);
paramCommand.Parameters.Add(myParameter);
}
The problem is passing paramType, it's SqlDbType and I don't know:
1.how to implement/use it here
2.when to calling this function.
NOTE: I just want to add parameters to my SQLCommand object. It's something like this:
SqlParameter myParameter = new SqlParameter("#user", SqlDbType.Char);
Something like this:
public static class CommandExtensions
{
public static void AddParameter(this IDbCommand command, string name, object value)
{
if (command == null) throw new ArgumentNullException("command");
if (name == null) throw new ArgumentNullException("name");
var p = command.CreateParameter();
p.ParameterName = name;
p.Value = value ?? DBNull.Value;
command.Parameters.Add(p);
}
}
which allows you to:
using (var command = connection.CreateCommand())
{
command.CommandText = "SELECT * FROM Users WHERE FirstName LIKE #name";
command.AddParameter("name", "J%");
// [...]
}
That code is also independent of the ADO.NET driver and can therefore be reused in most projects that use ADO.NET. IF you want more information about writing reusable ADO.NET code, read my article: http://blog.gauffin.org/2013/01/ado-net-the-right-way/
The problem is passing paramType, it's SqlDbType and I don't know
Typically you do not have to specify the db type.
Your approach is correct:
cmd.Parameters.Add(new SqlParameter("#Name", "Frank Rizzo"));
One thing to note is that SqlParameter constructor provides a number of overloads, making creating of a separate function to return new SqlParameter largely unnecessary.
In addition to jgauffin's answer:
When constructing an SqlParameter, if you are not sure about the SqlDbType of the parameter, you can use the SqlParameter constructor which only takes, parameter name and value as parameters. Namely; SqlParameter Constructor (String, Object).
In order to MSDN documentation,
When you specify an Object in the value parameter, the SqlDbType is
inferred from the Microsoft .NET Framework type of the Object.
There are a number of ways to add SQL parameters in ADO.NET. Generally it is not necessary to provide a SQL database type as data is sent as a string and implicitly converted by SQL server.
MSDN quote the following examples-
command.Parameters.Add("#ID", SqlDbType.Int);
command.Parameters["#ID"].Value = customerID;
// Use AddWithValue to assign Demographics.
// SQL Server will implicitly convert strings into XML.
command.Parameters.AddWithValue("#demographics", demoXml);
The first example could also be written as-
command.Parameters.Add("#ID", SqlDbType.Int).Value = customerID;
See http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.parameters(v=vs.100).aspx for more.
Obviously providing data which does not match the SQL data type will cause a SQL exception, you should set length restrictions and validate input, converting it to a compatible type locally using the "as" syntax can be useful as can regular expressions.
jgauffin's answer could easily be adapted to use the syntax that includes the DB type but I'm not sure what the advantage is (except as a reminder to you) as you get no type warnings regardless of values assigned, or even a exception before an attempt to execute the command.

Unicode SQL Query W/ Parameter instead N Prefix

I have an insert query to execute from within a C# against a SQL Server database.
The column I am inserting to is of type nvarchar.
the data I am inserting to that column is non-english.
Is it sufficient for me to use AddWithValue in order to pass the non-english data to the server? like this example:
string dogName = "עברית";
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand("INSERT INTO Dogs1(Name) VALUES #Name", connection))
{
command.Parameters.AddWithValue("Name", dogName);
command.ExecuteNonQuery();
}
}
Or must I use the N prefix to declare it unicode? like it says so here.
If I am understanding the question correctly, you can explicitly set the SqlCommand parameter to be a specific data type. You will be able to set it to be nvarchar as shown by the following link: http://msdn.microsoft.com/en-us/library/yy6y35y8.aspx
This below code snippet is taken directly from MSDN:
SqlParameter parameter = new SqlParameter();
parameter.ParameterName = "#CategoryName";
parameter.SqlDbType = SqlDbType.NVarChar;
parameter.Direction = ParameterDirection.Input;
parameter.Value = categoryName;
This uses an explicitly created SqlParameter instance, but it is the same idea by indexing the SqlParameterCollection of the SqlCommand instance.
I believe the link at the bottom is only really talking about values within SQL itself.
As far as I'm aware, the code you've got should be absolutely fine - otherwise there'd be no way of specifying Unicode text.
Of course, it's probably worth validating this - but I'd be very surprised if it didn't work.

Invalid parameter type between C# and Oracle

I have a function in Oracle that returns a sequence number. When I try to get that value in C# by a parameter it always tells me that the parameter type is invalid. A sample value of that returned value is 115545. If indeed this error is correct then what is the correspondent in ODBCType for this value? If it isn't correct then what is the problem?
Oracle function is:
FUNCTION Get_Next_Message_Id__
RETURN NUMBER IS
temp_ NUMBER;
CURSOR get_in_message_id_seq IS
SELECT in_message_id_seq.NEXTVAL
FROM dual;
BEGIN
General_SYS.Init_Method(lu_name_, 'IN_MESSAGE_API', 'Get_Next_Message_Id__', TRUE);
OPEN get_in_message_id_seq;
FETCH get_in_message_id_seq INTO temp_;
CLOSE get_in_message_id_seq;
RETURN(temp_);
END Get_Next_Message_Id__;
C# Code:
OdbcConnection myConnection = new OdbcConnection(ODBC_CLass.ifsconnectionstring);
OdbcParameter next_id = new OdbcParameter();
next_id.Direction = ParameterDirection.Output;
myConnection.Open();
OdbcCommand command = new OdbcCommand("{? = call ifsapp.in_message_api.Get_Next_Message_Id__}", myConnection);
command.CommandType = CommandType.StoredProcedure;
next_id = command.Parameters.Add("temp_", OdbcType.Int);
int k = command.ExecuteNonQuery();
MessageBox.Show("next_id: " + next_id.Value);
I believe the problem is in the way you're setting next_id. You're first creating an OdbcParameter and setting its direction - but then completely ignoring it, and reassigning the variable using the Add method, which will be creating an "in" parameter by default. Try this instead:
OdbcParameter nextId = command.Parameters.Add("temp_", OdbcType.Int);
nextId.Direction = ParameterDirection.Output;
Note that you should also be using using statements for the connection and command, to ensure they're cleaned up at the end of the code, whatever happens.

Categories

Resources