C# adding large bytearray(image) as paramter to dbcommand - c#

I'm currently in the process of creating a manual DB layer for a project. I've stumbled over a problem when I tried to store byte arrays (images) larger than 8k.
Normally I use the following to do create the commands and fill the parameters:
DbCommand cmd = new SqlCommand("INSERT INTO test1 VALUES (#mail, #picture)");
i=cmd.DeclareParameter(cmd, "mail", DbType.String, "mail");
if (i>0)
{
cmd.Parameters[i].Value = mailData;
}
(The above is cut together from multiple methods I use).
Now when I try to add the picture (which is the byte[]) I get the problem that I need to use SqlDbType.VarBinary there.
I've seen a few solutions that use .Parameters.Add but the Add I have only takes 1 (and not 2 parameters like in the examples I saw). Then when I try to create my own parameter with cmd.CreateParameter the DbType only takes a DbType and does not want an SqlDbType.
What would I have to do here to be able to add the byte[] as parameter (for byte arrays larger than 8k)?
tnx

Would SqlDbType.Image be more appropriate?
If not, consider Row Overflowing
You're telling it to use DbCommand rather than SqlDbCommand.
Try this:
using(var command = new SqlCommand(#"INSERT INTO test1 VALUES (#mail, #picture)"))
{
command.Parameters.Add(#"mail", SqlDbType.Image);
if (i > 0)
{
command.Parameters[i].Value = mailData;
}
}
(I'd add this as a comment, but I can't so I shant.)

when I try to create my own parameter with cmd.CreateParameter the DbType only takes a DbType and does not want an SqlDbType
That's because you declared the command as a DbCommand instead of a SqlCommand. If you declare it as a SqlCommand it should work:
|------
V
SqlCommand cmd = new SqlCommand("INSERT INTO test1 VALUES (#mail, #picture)");
cmd.Parameters.AddWithValue("#mail", mailData);
SqlParameter p = cmd.Parameters.Add("#picture", SqlDbType.VarBinary);
p.Value = {picture data};

If your files are really large you can consider streaming into the BLOB (image) column. See http://msdn.microsoft.com/en-us/library/hh556234(v=vs.110).aspx.

You need to specify the length -1 for the parameter. Otherwise it will be VARBINARY(8000). With an explicit length of -1 it will be VARBINARY(MAX), which is what you need.

Related

String value in byte[] c#

I have to do a query to insert a value in a SQL table. The type of the value is varbinary and I have a string to insert with an hex value in it. So I tried to use the SQL Convert Function like this:
using (SqlCommand dbCommand = new SqlCommand("INSERT INTO [Link] ([Record]) values (CONVERT(varbinary,#myrecord);", dbConn))
dbCommand.Parameters.Add("myrecord", System.Data.SqlDbType.VarBinary).Value = recordString;
but I have this Error: Failed to convert parameter value from a String to a
Byte[].
So I tried to convert my string to byte[], but all the function I found also on this site convert my string to byte changing its value, so it's not good because my string has inside the value I need to insert in the table.
Recap: I have a string with this value: "0x54000000006C00000000099W043100300030003100" how can I add it in a SQL table with a varbinary field?
Ok, i think i understand now. If you are using sql server 2008+, you can do this:
using (SqlCommand dbCommand = new SqlCommand("INSERT INTO [Link] ([Record]) values (CONVERT(varbinary,#myrecord,1);", dbConn))
dbCommand.Parameters.Add("myrecord", System.Data.SqlDbType.VarChar).Value = recordString;
Notice the 1 in CONVERT(varbinary,#myrecord,1). Btw, the example number you gave us is not a valid Hex number...
More info: Msdn
you can and should be able to do this make sure you adjust the VarBinary Size to fit your case
using(SqlCommand dbCommand = new SqlCommand("INSERT INTO [Link] ([Record]) values(#myrecord);", dbCon))
{
// Replace 8000, below, with the correct size of the field
dbCommand.Parameters.Add("#myrecord", System.Data.SqlDbType.VarChar, recordString.Length).Value = recordString;
dbCommand.ExecuteNonQuery();//wrap around a try catch if you need to catch exceptions
}

Issue in updating MS Access records using oledbcommand.executeNonQuery(), result not updating

I am posting a query first time here, So, Please ignore my formatting.
I am trying to update my .accdb file using update command, but result of oledbcommand.executeNonQuery() is 0 hence result is not updating in the database.
Though I am receiving no errors.
Here is what I am doing.
string vsql = string.Format("UPDATE DefTask_List SET [Action]=#Action WHERE [SNo]=#SNo");
vcom.Parameters.AddWithValue("#SNo", row.Cells[0].Value.ToString());
vcom.Parameters.AddWithValue("#Action", comboBox1.Text);
OleDbCommand vcom = new OleDbCommand(vsql, vcon);
vcon.Open();
int k = vcom.ExecuteNonQuery();
vcom.Dispose();
vcon.Close();
Please note that SNo is an autonumber in my .accdb file also with the same way I am inserting and deleting data but that is working fine.
OleDbCommand doesn't support named parameters. The only matter is their orders.
From OleDbCommand.Parameters property
The OLE DB .NET Provider does not support named parameters for passing
parameters...
Therefore, the order in which OleDbParameter objects are added to the
OleDbParameterCollection must directly correspond to the position of
the question mark placeholder for the parameter in the command text.
That's why your first #Action in OleDbCommand matches with #SNo in your AddWithValue and #SNo matches with your #Action in your AddWithValue.
Since probably you don't have a data like this, there will be no update operation.
Switch your parameter orders and use .Add method which is recommended instead of AddWithValue. It may generate unexpected results. Read;
Can we stop using AddWithValue() already?
Also use using statement to dispose your OleDbConnection and OleDbCommand instead of calling .Dispose() and .Close() methods manually.
using(OleDbConnection vcon = new OleDbConnection(conString))
using(OleDbCommand vcom = vcon.CreateCommand())
{
vcom.CommandText = "UPDATE DefTask_List SET [Action]=#Action WHERE [SNo]=#SNo";
vcom.Parameters.Add("?", OleDbType.VarChar).Value = comboBox1.Text;
vcom.Parameters.Add("?", OleDbType.Integer).Value = (int)row.Cells[0].Value;
// I assume your column types are NVarchar2 and Int32
vcon.Open();
int k = vcom.ExecuteNonQuery();
}

Is a cursor parameter really to be declared differently than a "regular" parameter?

OK, nobody seems to know how to solve the problem I'm having looping through a cursor/result set for storage into a List, so I'm going to break it down into pieces and try to slog through it that way. So, first of all:
I add SQL Parameters to an OracleCommand object this way (works fine):
cmd.Parameters.Add("ABCID", _ABCID);
cmd.Parameters["ABCID"].Direction = ParameterDirection.Input;
cmd.Parameters["ABCID"].DbType = DbType.String;
IOW, when I add the param, I pass the name of the parameterized portion of the SQL ("ABCID" above) and a value to give it (_ABCID is a variable that has been assigned, let's say, "42").
However, when adding a Cursor (output) param, it seems to want, not a value (such as an initialized cursor object), but simply the data type:
cmd.Parameters.Add("cur", Devart.Data.Oracle.OracleDbType.Cursor);
cmd.Parameters["cur"].Direction = ParameterDirection.Output;
(I tried both ways, and neither one works, so...?)
Verily/thus, my question is: Is this really the correct way of declaring a Cursor parameter to be outputted back for traversal/access?
I'm using the brand new version of DevArt DotConnect components (6.80.332), VS 2010, .NET 4
Updated:
Here's the code in more context:
public void PopulateCurrentUserRoles(String AUserName, List<String> ACurrentUserRoles) {
_UserName = AUserName;
String query = "select roleid from ABCrole where ABCid = :ABCID";
Devart.Data.Oracle.OracleCommand cmd = new Devart.Data.Oracle.OracleCommand(query, con);
cmd.CommandType = CommandType.Text;
int _ABCID = GetABCIDForUserName();
cmd.Parameters.Add("cur", Devart.Data.Oracle.OracleDbType.Cursor);
cmd.Parameters["cur"].Direction = ParameterDirection.Output;
cmd.Parameters.Add("ABCID", _ABCID);
cmd.Parameters["ABCID"].Direction = ParameterDirection.Input;
cmd.Parameters["ABCID"].DbType = DbType.String;
//cmd.ExecuteNonQuery(); blows up: "illegal variable name/number"
//cmd.ExecuteCursor(); " "
//cmd.ExecuteReader(); " "
Devart.Data.Oracle.OracleCursor oraCursor =
(Devart.Data.Oracle.OracleCursor)cmd.Parameters["cur"].Value;
Devart.Data.Oracle.OracleDataReader odr = oraCursor.GetDataReader(); // "Object reference not set to an instance of an object"
while (odr.Read()) {
ACurrentUserRoles.Add(odr.GetString(0));
}
}
the following is from the Oracle Data Provider for .NET Developer's Guide. yes, I know, "Devart". Nonetheless, It suggests the following:
Be careful with your parameter typing declaration.
add that cursor/output parameter to the Parameters collection before
any others.
As a long shot... my guide shows a OracleDbType.RefCursor but not a OracleDbType.Cursor. If DevArt has RefCursor, try that. In visual studio, what type does .NET think that parameter is? This question is not as dumb as I used to think.
... On the other hand, if the parameter is set as an OracleDbType.Char type by setting the OracleDbType property, the output data is returned
as an OracleString type. If both DbType and OracleDbType properties
are set before the command execution, the last setting takes affect.
. . .
"An application should not bind a value for output parameters; it is
the responsibility of ODP.NET to create the value object and populate
the OracleParameter Value property with the object. When binding by
position (default) to a function, ODP.NET expects the return value to
be bound first, before any other parameters."
EDIT:
Based on #Clay's self-answer... so there is no parameter specified for the output, rather one simply does this: OracleDataReader odr = cmd.ExecuteReader();
Straight from the horse's mouth (the DevArt folks):
_UserName = AUserName;
// From the DevArtisans:
String query = "select roleid from ABCrole where ABCid = :ABCID";
Devart.Data.Oracle.OracleCommand cmd = new Devart.Data.Oracle.OracleCommand(query, con);
cmd.CommandType = CommandType.Text;
int _ABCID = GetABCIDForUserName();
cmd.Parameters.Add("ABCID", _ABCID);
cmd.Parameters["ABCID"].Direction = ParameterDirection.Input;
cmd.Parameters["ABCID"].DbType = DbType.String;
Devart.Data.Oracle.OracleDataReader odr = cmd.ExecuteReader();
while (odr.Read()) {
ACurrentUserRoles.Add(odr.GetString(0));
}
To quote Casey and the Sonshine Banned, "That's the way, Uh huh Uh huh, I like it, Uh huh Uh huh"; actually, I can't stand that crap, but I do kind of relate to that sentiment right about now.

ASP.net c# simple query paramter question

// Add into DB
using (tblArtworkTemplatesTableAdapter tblAdapter = new tblArtworkTemplatesTableAdapter())
{
tblAdapter.Insert(DateTime.Now, "#specID");
"#specID" = int.Parse(lstChooseSpec.SelectedValue)
}
I know the code is wrong, just for illustration of my objective, how do I paramatise the input?
Generally it depends. If You are using any kind of ORM like LINQ to SQL or NHibernate, it will do it for You no questions asked. If YOu are doing it using Plain ADO objects (which I suppose is the case) then You will have to comeup with the Command (or SQLCommand or any other ICommand implementation) object and use SQLParameter class (or other parameter classes).
ICommand has the collection of parameters that You can arbitralily edit.
SqlCommand cmd = new SqlCommand(
"select * from STH where column = #SpecID", conn);
//it might be useful to specify a type as well
SqlParameter param = new SqlParameter();
param.ParameterName = "#SpecID";
//I woudl use the TryParse method though
param.Value = int.Parse(lstChooseSpec.SelectedValue);
cmd.Parameters.Add(param);
This line
"#specID" = int.Parse(lstChooseSpec.SelectedValue)
Is incorrect. You can't assign a value to a constant. You might mean something like
specId = int.Parse(lstChooseSpec.SelectedValue);
The rest of the code is confusing. Why are you parsing lstChooseSpec.SelectedValue to an integer, then trying to add it to the adapter as a DateTime? C# is strongly-typed: something is either an int or a DateTime, but cannot be both.
It might help if you could post the rest of the method.
Also, have a look at this overview on MSDN.

ADO.NET - The Size property has an invalid size of 0

I'm trying to get output value from DB via ADO.NET. There's a client code:
using (var connection = new SqlConnection(ConnectionString))
{
connection.Open();
SqlCommand command = new SqlCommand("pDoSomethingParamsRes", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("#i", 1);
var outParam = new SqlParameter("#out", SqlDbType.VarChar);
outParam.Direction = ParameterDirection.Output;
command.Parameters.Add(outParam);
command.ExecuteNonQuery();
Console.WriteLine(command.Parameters["#out"].Value.ToString());
}
When I run this I get the following exception:
the Size property has an invalid size of 0
According to manual SqlParameter.Size Property I might omit size. Why do I get this exception?
How to make it work without passing size?
VarChar and NVarChar are variable width character fields (thus var+char). You have to set the length, otherwise the default is zero.
Parameter Size is required for variable size Output parameters. Generally ADO.NET decides the size of the parameter based on the Value assigned to the parameter (hence it is optional), but in output parameter since no value is Set, you need provide the size required for the parameter
Set the Parameter size to size of the output variable from the DB... Say 50
outParam.Size = 50;
Incidentally, setting the size property of an output parameter is necessary even if it isn't a string-type parameter. For example, if you are using a System.Data.SqlDbType.Int, you should set the size to be 4.
Check MSDN : SqlParameter.Size Property
For bidirectional and output parameters, and return values, you must set the value of Size. This is not required for input parameters, and if not explicitly set, the value is inferred from the actual size of the specified parameter when a parameterized statement is executed.
Everyone's answer was about as clear as mud to me. Maybe this will help someone now that I found what worked.
Need to add size to the parameter
DynamicParameters Params = new DynamicParameters();
Params.Add("#ProfileID", ProfileID);
Params.Add("#CategoryName", CategoryName);
Params.Add("#Added", dbType: DbType.String, direction: ParameterDirection.Output,size:10);
db.Execute(sql, Params, commandType: CommandType.StoredProcedure, commandTimeout: 60);
var Added = Params.Get<string>("#Added");
I'm not sure if this is the same problem i've had before, but using a byte for a parameter can sometimes lead to this error.
Try this. Explicitly declare the i parameter as a variable.
THEN assign it's value with the Value property.
Also, you can get the actual size of the parameters by inspecting the sproc with this little command:
SqlCommandBuilder.DeriveParameters(yourCommand)
and then just foreach your way through the parameters collection.
I had this error occur, supplying a value that had a non-string, but nullable, type. In my case, an int?. I fixed it by passing in a non-nullable int instead.
you have to set Size for parameter output
using (var connection = new SqlConnection(ConnectionString))
{
connection.Open();
SqlCommand command = new SqlCommand("pDoSomethingParamsRes", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("#i", 1);
var outParam = new SqlParameter("#out", SqlDbType.VarChar);
outParam.Direction = ParameterDirection.Output;
outParam.Size = 50; // this is example
command.Parameters.Add(outParam);
command.ExecuteNonQuery();
Console.WriteLine(command.Parameters["#out"].Value.ToString());
}
I had the same error and below is my code that works
cmd.Parameters("#ProjectKey").SqlDbType = SqlDbType.NVarChar
cmd.Parameters("#ProjectKey").Size = 150
cmd.Parameters("#ProjectKey").Direction = ParameterDirection.InputOutput
cmd.ExecuteNonQuery()

Categories