How to pass Byte Array in a Query using C#? - c#

I'm trying to insert bytes of byte array in the database. using following code.
String query = String.Format(#"INSERT INTO [Documents]
([InsertedBy], [DocumentName], [Document])
VALUES
('{0}','{1}',{2})",
insertedBy, docName, docBytes);
Cmd.CommandText = query;
Cmd.ExecuteNonQuery();
Following exception is occured:
An object or column name is missing or empty. For SELECT INTO
statements, verify each column has a name. For other statements, look
for empty alias names. Aliases defined as "" or [] are not allowed.
Change the alias to a valid name. Incorrect syntax near ''.
I'm not getting what the reason is.

Never use string concatenation or string functions to make parametrized queries.
Also, because (I suspect that) docBytes is a byte[], string concatenation will not have the results that you hope for.
Here is how I would do it:
private static void InsertDocument(SqlCommand cmd, int insertedBy, string docName, byte[] docBytes)
{
cmd.CommandText = #"INSERT INTO [Documents]
([InsertedBy], [DocumentName], [Document])
VALUES
(#insertedBy,#docName,#docBytes)";
cmd.Parameters.Add("insertedBy", SqlDbType.Int).Value = insertedBy;
// Note: consider using `nvarchar` instead of `varchar`;
cmd.Parameters.Add("docName", SqlDbType.VarChar, 100).Value = docName;
// Note: -1 maps to the nvarchar(max) length;
cmd.Parameters.Add("docBytes", SqlDbType.VarBinary, -1).Value = docBytes;
// The following call presupposes that the associated `SqlConnection` is open
cmd.ExecuteNonQuery();
}

If your insertedBy column is an int, you don't need to use single quotes with it. Because you are try to insert characters to your int typed column.
Just use it like;
string query = String.Format(#"INSERT INTO [Documents]
([InsertedBy], [DocumentName], [Document])
VALUES
({0},'{1}',{2})",
insertedBy, docName, docBytes);
But since we don't know your values, this is the only suggestion I have.

Related

Inserting byte array into SQL Server

I am constructing a sql_insert_string to be used in Microsoft.ApplicationBlocks.Data.SqlHelper to be used as follows:
SqlHelper.ExecuteNonQuery(Transaction, CommandType.Text, sql_insert_string)
When I hover over the SQL statement it looks like below:
string sql_insert_string = "Insert into images_table(image_id, image_byte_array) values ('123', System.Byte[])
One of the insert value is a byte array as shown above. The variable has value in the byte array, say like byte[6738] . But after the sql_insert_string is constructed, it comes as System.Byte[]. The image_byte_array column type is varbinary(max). The database is SQL Server 2008. Because of this the database throws the following error:
An object or column name is missing or empty. For SELECT INTO statements, verify each column has a name. For other statements, look for empty alias names. Aliases defined as \"\" or [] are not allowed. Change the alias to a valid name.
you can insert the byte array like so:
private void FireSql(byte[] input)
{
const string sql_insert_string =
"Insert into images_table(image_id, image_byte_array) values (#image_id, #image_byte_array)";
SqlTransaction transaction = null; //wherever you get the transaction obj from.
var imageIdParam = new SqlParameter("#image_id", SqlDbType.Int, 4)
{
Direction = ParameterDirection.Input,
Value = 123
}; //change the data type to whatever data type you are expecting
var byteParam = new SqlParameter("#image_byte_array", SqlDbType.VarBinary)
{
Direction = ParameterDirection.Input,
Size = input.Length,
Value = input
}; //change the data type to whatever data type you are expecting
SqlHelper.ExecuteNonQuery(transaction, CommandType.Text, sql_insert_string, imageIdParam, byteParam);
}
I would suggest looking at an ORM (https://en.wikipedia.org/wiki/Object-relational_mapping) like Entity Framework(http://www.asp.net/entity-framework) to do all of this for you while increasing security and future changes much easier.
You should be using the Parameters while constructing the SQL Query which obviously will avoid SQL Injection attacks. How your queries are getting constructed is still unclear here.
Something like this should do it for you.
SqlParameter sParam = new SqlParameter("#image_byte_array", SqlDbType.VarBinary)
{
Value = image
};
SqlHelper.ExecuteNonQuery(Transaction, CommandType.Text, sql_insert_string, sParam)
You may use
string sql_insert_string =
String.Format("INSERT INTO images_table(image_id, image_byte_array) VALUES ('123', CAST('{0}' AS VARBINARY(MAX)))", System.Byte[].ToString());
And yes, as #marc_s commented, you shouldn't be constructing SQL statements as a security concern.

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
}

Insert SQL with parameters causes "Incorect syntax near the keyword 'values'"

I want to populate a table in mssql with the values entered by the user (the error comes from the NumericUpDown) and I'm using this code:
string cs= "Data Source=CODRINMA\\CODRINMA;Initial Catalog=BusManager; Trusted_Connection=True;";
string insert = "INSERT INTO TipAutocar ([IDTipAutocar], [Marca], [Model], [Nrlocuri] values ([#TipAutocar], [#Marca], [#Model], [#Nrlocuri]))";
try
{
using (SqlConnection con = new SqlConnection(cs))
{
con.Open();
SqlCommand cmd = new SqlCommand(insert, con);
cmd.Parameters.AddWithValue("#IDTipAutocar", txtID.Text);
cmd.Parameters.AddWithValue("#Marca", txtMarca.Text);
cmd.Parameters.AddWithValue("#Model", txtModel.Text);
cmd.Parameters.AddWithValue("#Nrlocuri", nmrLocuri.Value);
int valoare = cmd.ExecuteNonQuery();
con.Close();
MessageBox.Show(valoare + "Tipul de autocar a fost adaugat cu succes!", "BusManager");
}
}
catch (Exception er) { MessageBox.Show(er.Message); }
But, when I press button to insert, I'm having the following error and I can't figure it out what's to do:
Incorect syntax near the keyword 'values'.
I'm missing a closing round parenthesis before values here:
string insert = "INSERT INTO TipAutocar ([IDTipAutocar], [Marca], [Model], [Nrlocuri] values ([#IDTipAutocar], [#Marca], [#Model], [#Nrlocuri]))";
You are not allowed to use [] around the parameters, otherwise it's not a parameter and you'll get an error f.e. "invalid columnname [#TipAutocar]".
You also name the parameter #TipAutocar but you add it as IDTipAutocar.
Also, always use the correct type, all the more if you use AddWithValue which infers the type from the value. So i guess that IDTipAutocar is an int, then parse it to one before:
cmd.Parameters.AddWithValue("#IDTipAutocar", int.Parse(txtID.Text));
As an aside, i'm always using a verbatim string literal. On that way i can format my sql query as i want, even with multiple lines. This should work as exptected:
string insert = #"INSERT INTO TipAutocar
( IDTipAutocar, Marca, Model, Nrlocuri )
VALUES
( #IDTipAutocar, #Marca, #Model, #Nrlocuri)";
Look at this bracket;
string insert = "INSERT INTO TipAutocar ([IDTipAutocar], [Marca], [Model], [Nrlocuri] values (#TipAutocar, [#Marca, #Model, #Nrlocuri))";
^^^
You close it at the end of your query, you should close it just before your VALUES part.
Change it to;
string insert = "INSERT INTO TipAutocar ([IDTipAutocar], [Marca], [Model], [Nrlocuri]) values (#TipAutocar, #Marca, #Model, #Nrlocuri)";
^^^ ^^^
You don't need are not allowed to use square brackets for your parameters by the way. Also use using statement to dispose your SqlCommand as well. And since you used this statement for your SqlConnection, you don't need to close it with con.Close() because this statement do that automaticaly.
Also you define your parameter name as #TipAutocar in your command but try to add parameter name as #IDTipAutocar which does not match. Change your parameter name like;
cmd.Parameters.AddWithValue("#TipAutocar", txtID.Text);
And don't use AddWithValue anymore. It may generate unexpected results. Use .Add() method overloads instead to specify your SqlDbType and parameter size.

i'm lost: what is wrong with this ado.net code?

well, the question is clear i hope, the code is this:
string sql = "delete from #tabelnaam";
SqlCommand sc = new SqlCommand();
sc.Connection = getConnection();
sc.CommandType = CommandType.Text;
sc.CommandText = sql;
SqlParameter param = new SqlParameter();
param.Direction = ParameterDirection.Input;
param.ParameterName = "#tabelnaam";
param.Value = tableName;
sc.Parameters.Add(param);
OpenConnection(sc);
sc.ExecuteScalar();
tableName is supplied to this function.
I get the exception:
Must declare the table variable #tabelnaam
IIRC, you cant use a substitute the table name for a parameter.
Rather build the SQL string containing the correct table name.
Make to changes
rather than using paramter use this
string sql = string.format( "delete from {0}",tableName);
make use of executenonquery intead of ExecuteScalar
sc.ExecuteNonQuery();
As mentioned by others, you can't parameterise the table name.
However, as you rightly mention in comments on other answers, using simple string manipulation potentialy introduces a SQL injection risk:
If your table name input is fro an untrusted source, such as user input, then using this:
string sql = string.format( "DELETE FROM {0}",tableName);
leaves you open to the table name "myTable; DROP DATABASE MyDb" being inserted, to give you:
DELETE FROM myDb; DROP DATABASE MyDB
The way round this is to delimit the table name doing something such as this:
string sql = string.format("DELETE FROM dbo.[{0}]", tableName);
in combination with checking that the input does not contain either '[' or ']'; you should probably check it also doesn't contain any other characters that can't be used as a table name, such as period and quotes.
I dont think you can parameterize the table name. From what I have read you can do it via Dynamic sql and calling sp_ExecuteSQL.
Your SQL is incorrect, you are deleting from a table variable yet you haven't defined that variable.
Update: as someone has pointed out, you are trying to dynamically build a query string but have inadvertantly used SQL parameters (these do not act as place holders for string literals).
More here:
Parameterise table name in .NET/SQL?
You cannot parameterise the table name, you have to inject it into the command text.
What you can and should do is protect yourself against SQL injection by delimiting the name thus:
public static string Delimit(string name) {
return "[" + name.Replace("]", "]]") + "]";
}
// Construct the command...
sc.CommandType = CommandType.Text;
sc.CommandText = "delete from " + Delimit(tableName);
sc.ExecuteNonQuery();
See here and here for more background info.

Full text search stored procedure error

This is the error I am getting:
Syntax error near 'online' in the full-text search condition '""online"*" and "and*" and ""text"*"'.
This is my stored procedure:
ALTER PROCEDURE dbo.StoredProcedure1
(
#text varchar(1000)=null
)
AS
SET NOCOUNT ON
declare #whereclause varchar(1000)
SET #whereclause = #text
SELECT articles.ArticleID AS linkid,
articles.abstract as descriptiontext,
articles.title as title,
'article' as source,
articles.releasedate as lasteditdate
FROM articles
WHERE CONTAINS(title, #whereclause)
ORDER BY lasteditdate DESC, source ASC
This what i pass to SP:
string content = "\"online\" and \"text\"";
part of C# code:
using (SqlConnection cn = new SqlConnection(this.ConnectionString))
{
SqlCommand cmd = new SqlCommand("StoredProcedure1", cn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#text", SqlDbType.VarChar).Value = searchExpression;
cn.Open();
UPDATE:
Strings that i try and errors that i get:
content = "online text";
Syntax error near 'text' in the full-text search condition 'online text'.
content = "\"online\" and \"text\"";
Syntax error near 'online' in the full-text search condition '""online"*" and "and*" and ""text"*"'.
content = "\"online and text\"";
Syntax error near 'online*' in the full-text search condition '""online*" and "and*" and "text"*"'.
From msdn:
Specifies the text to search for in column_name and the conditions for a match.
is nvarchar. An implicit conversion occurs when another character data type is used as input.
Because "parameter sniffing" does not work across conversion, use nvarchar for better performance.
So i've changed everything to nvarchar:
cmd.Parameters.Add("#text", SqlDbType.NVarChar).Value = searchExpression;
declare #whereclause nvarchar(1000)
I think SQl uses % instead of *
Try this one in your c# code when adding parameter:
cmd.Parameters.Add("#text", searchExpression);
The problem is with the extra quotation marks.
Instead of this:
string content = "\"online\" and \"text\"";
try this:
string content = "online and text";
It will generate a correct condition:
'"online*" and "and*" and "text*"'
Also if accept user input and pass it directly into a query like this - you are really opening your application to SQL injection.
Not sure if it's significant, but your procedure is expecting varchar and your calling code is saying the parameter is SqlDbType.Char.
I'm quite fond of DeriveParameters :
SqlCommand cmd = new SqlCommand("StoredProcedure1", cn);
cmd.CommandType = CommandType.StoredProcedure;
cn.Open()
SqlCommandBuilder.DeriveParameters cmd;
cmd.Parameters("#text").Value = searchExpression;
I use this method to remove slashes and then pass the resulting char array to sp.
public static char[] RemoveBackslash(string value)
{
char[] c = value.ToCharArray();
return Array.FindAll(c, val => val != 39).ToArray();
}
string content = "'\"online\" and \"text\"'";
Sqlparam = new SqlParameter("#search", SqlDbType.NVarChar);
Sqlparam.Value = RemoveBackslash(content);
Sqlcomm.Parameters.Add(Sqlparam);

Categories