datatable not accepting the value of varbinary - c#

the value buf has a datatype varbinary(max) and the value is 0x0000002D
string buF =
"0x" + BitConverter.ToString((byte[])dt.Rows[i]["BuF"]).Replace("-", "");
Label3.Text = buF;
i use the value to find the fileid
DataTable dt = new DataTable();
SqlConnection connection = new SqlConnection();
connection.ConnectionString = ConfigurationManager.ConnectionStrings["XYZ"].ConnectionString;
connection.Open();
SqlCommand sqlCmd = new SqlCommand("SELECT FileID FROM Backed where MachineID = #machineID AND BuF =#buF", connection);
SqlDataAdapter sqlDa = new SqlDataAdapter(sqlCmd);
sqlCmd.Parameters.AddWithValue("machineID", strID);
sqlCmd.Parameters.AddWithValue("buF", buF);
sqlDa.Fill(dt);
connection.Close();
i does not use the value of buf and i dont get the correct filid....
but if i use this with the value0x0000002D instead of buf i get the file id... why is this happening... i tried everything but nothing seems to work
i need help

The equivalent type for varbinary in C# is byte[], not string. Also, as Hogan said, AddWithValue tries to assume a data type. Instead, you can make it explicit:
sqlCmd.Parameters.Add("buF", SqlDbType.VarBinary, -1).Value = yourByteArray;
The -1 for length corresponds to varbinary(max).

It would be better to work with the binary data as byte[] and not use strings and string conversions if you don't have to. Here is a complete example that should work to demonstrate how to read and query varbinary(max) types.
static void Test(SqlConnection openConnection)
{
using(SqlCommand cmd = openConnection.CreateCommand())
{
cmd.CommandText =
#"create table #Test
(bin varbinary(max), num int);
insert into #Test (bin, num)
values (0x0000002D, 1);";
cmd.ExecuteNonQuery();
cmd.CommandText = "SELECT TOP 1 bin FROM #Test;";
byte[] binValue = (byte[])cmd.ExecuteScalar();
cmd.CommandText = "SELECT * FROM #Test WHERE bin = #bin;";
var parameter = new SqlParameter("#bin", SqlDbType.VarBinary, -1);
cmd.Parameters.Add(parameter);
parameter.Value = binValue;
DataTable table = new DataTable();
using (var reader = cmd.ExecuteReader())
{
table.Load(reader);
}
Debug.Assert(table.Rows.Count == 1);
}
}

AddWithValue makes a parameter of the type it sees. When you pass a long it uses a number, when a string it uses the ascii. Try this:
sqlCmd.Parameters.AddWithValue("buF",long.Parse(buF));

Related

To set image url by converting byte to string and access other values from database stored procedure

The stored procedure:
create procedure spGetImageId
#Id int
as
Begin
select imageData
from uploadTable
where ID = #Id
End
C# code calling it:
protected void Page_Load(object sender, EventArgs e)
{
string cs = ConfigurationManager.ConnectionStrings["CHTproductionConnectionString"].ConnectionString;
using (SqlConnection con=new SqlConnection(cs))
{
SqlCommand cmd = new SqlCommand("spGetImageId", con);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter paramID = new SqlParameter()
{
ParameterName = "#Id",
Value = Request.QueryString["ID"]
};
cmd.Parameters.Add(paramID);
con.Open();
byte[] bytes = (byte[])cmd.ExecuteScalar();
string strBase64 = Convert.ToBase64String(bytes);
Image1.ImageUrl = "data:Image/png;base64," + strBase64;
}
}
It is viewing uploaded image from the database and id is reading from the url. If I change my stored procedure to
create procedure spGetImageId
#Id int
as
Begin
select title, description, imageData
from uploadTable
where ID = #Id
End
How can I access title and description by adding inside this code? Image changes with the change of id in the url.
The process is working. I just need to access title and description
Others have already given you an answer, but I thought splitting everything up should be a good advice.
Creating a method for bits of code that you'll probably need to reuse is a good practice. Executing a stored procedure often qualifies.
public string ConnectionString
{
get
{
return ConfigurationManager.ConnectionStrings["CHTproductionConnectionString"].ConnectionString;
}
}
public DataTable GetDataTableFromSproc(string sproc, SqlParameter[] parameters)
{
using (SqlConnection con = new SqlConnection(this.ConnectionString))
using (SqlCommand cmd = new SqlCommand(sproc, con) { CommandType = CommandType.StoredProcedure })
using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
{
con.Open();
cmd.Parameters.AddRange(parameters);
DataTable dt = new DataTable();
adapter.Fill(dt);
return dt;
}
}
Then you've got a reusable method to call like so
protected void Page_Load(object sender, EventArgs e)
{
SqlParameter[] parameters = new SqlParameter[1];
parameters[0] = new SqlParameter("#Id", SqlDbType.Int) { Value = Convert.ToInt32(Request.QueryString["ID"]) };
DataTable dt = this.GetDataTableFromSproc("spGetImageId", parameters);
string title = dt.Rows[0]["title"].ToString();
string description = dt.Rows[0]["description"].ToString();
Image1.ImageUrl = "data:Image/png;base64," + Convert.ToBase64String((byte[])dt.Rows[0]["imageData"]);
}
cmd.ExecuteScalar
This is going to return you the first column of the first row returned. This is useful if you just need to get a single thing from a procedure, but in your case, you need to get multiple.
To do this, you need to use a SqlDataAdapter. Without refactoring your code, you can do the following. Although, I would suggest splitting out into a function that is used to retrieve the data and another that loads it into an object you can use.
string cs = ConfigurationManager.ConnectionStrings["CHTproductionConnectionString"].ConnectionString;
using (SqlConnection con = new SqlConnection(cs))
{
SqlDataAdapter Adapter = new SqlDataAdapter();
DataSet TempData = new DataSet();
SqlCommand cmd = new SqlCommand("spGetImageId", con);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter paramID = new SqlParameter()
{
ParameterName = "#Id",
Value = Request.QueryString["ID"]
};
cmd.Parameters.Add(paramID);
con.Open();
Adapter.SelectCommand = cmd;
Adapter.Fill(TempData);
string title = TempData.Tables[0].Rows[0]["title"].ToString();
string description = TempData.Tables[0].Rows[0]["description"].ToString();
string imageBytes = TempData.Tables[0].Rows[0]["imageData"].ToString();
string strBase64 = Convert.ToBase64String(imageBytes );
Image1.ImageUrl = "data:Image/png;base64," + strBase64;
}
Your main problem when trying to get the extra data is that ExecuteScalar() only returns the first column of the first row from what the recordset. To retrieve more than that requires the use of the ExecuteReader() method and using a DataReader, DataTable, or DataAdapter to go through the set.
Other changes:
Request.QueryString returns a string within an object and can be null. If someone should alter the string to text it will throw an error when the SQL executes. I added in 'int ImageID` to contain this
I added in string variables and hoisted them for the other data (title, desc)
Utilized try/catch/finally
Did a null check on the image data prior to assigning to the Image control. The Title & Description values are there as well for your convenience,
I replaced the distinct Sql Parameter with the direct cmd.Parameters.AddWithValue() method.
This is how it looks now:
protected void Page_Load(object sender, EventArgs e) {
string cs = ConfigurationManager.ConnectionStrings["CHTproductionConnectionString"].ConnectionString;
int ImageID;
string ImgTitle;
string ImgDesc;
string ImgBytes;
string strBase64;
if (!int.TryParse((string)Request.QueryString["ID"]), out ImageID) {
// STOP: querystring is not a number
}
else {
using (SqlConnection con=new SqlConnection(cs)) {
SqlCommand cmd = new SqlCommand("spGetImageId", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#Id", ImageID);
try {
con.Open();
var reader = cmd.ExecuteReader();
if (reader.Read()) {
ImgTitle = reader[0].ToString();
ImgDesc = reader[1].ToString();
ImgBytes = reader[2].ToString();
strBase64 = Convert.ToBase64String(ImgBytes);
}
}
catch (Exception ex) {
// handle exception
}
finally {
cmd.Dispose();
conn.Close();
}
}
}
if (strBase64 != null) {
Image1.ImageUrl = "data:Image/png;base64," + strBase64;
// utilize ImgTitle
// utilize ImgDesc
}
}

How to Handle SQL Exception Must Pass Parameter number 'x'?

I am trying to store Binary Data by using store procedure. Store procedure has three parameters. Last parameter will be containing Binary Data. But when I run a code it gives SQL Exception
Must pass parameter number 3 and subsequent parameters as '#name =
value'. After the form '#name = value' has been used, all subsequent
parameters must be passed in the form '#name = value'.
SqlCommand cmd = new SqlCommand("EXEC myProc #param1 = 8, #param2= '5.png', #FileSignature");
using (SqlConnection conn = new SqlConnection(myConnString))
{
cmd.Connection = conn;
if (FileSignature == null) //FileSignature is byte[]
{
cmd.Parameters.Add("#FileSignature", SqlDbType.VarBinary, -1);
cmd.Parameters["#FileSignature"].Value = System.DBNull.Value;
}
else
cmd.Parameters.AddWithValue("#FileSignature", FileSignature); //FileSignature is byte[]
int iReturn = cmd.ExecuteNonQuery();
}
You can't use #param=val for some parameters and #param for others.
Also, this is not the proper way to execute a stored procedure using sqlCommand.
Please try reading the exception message. It's plain english and is there to help.
Try this:
using(SqlConnection conn = new SqlConnection(myConnString),
SqlCommand cmd = new SqlCommand("myProc", conn)
{
cmd.CommandType = SqlCommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#param1", 8);
cmd.Parameters.AddWithValue("#param2", '5.png');
if (FileSignature == null) //FileSignature is byte[]
{
cmd.Parameters.Add("#FileSignature", SqlDbType.VarBinary, -1);
cmd.Parameters["#FileSignature"].Value = System.DBNull.Value;
}
else
{
cmd.Parameters.AddWithValue("#FileSignature", FileSignature); //FileSignature is byte[]
}
conn.Open();
int iReturn = cmd.ExecuteNonQuery();
conn.Close();
}
Because you supplied the first two parameters by name you must do so for all three. So you need to update you SqlCommand text to include it SqlCommand cmd = new SqlCommand("EXEC myProc #param1 = 8, #param2= '5.png', **#Parameter3** = #FileSignature");
Replace #Parameter3 with the name from your Stored Proc or optional you could just not pass any names (as long as the parameters are in the same order in your procedure.
SqlCommand cmd = new SqlCommand("EXEC myProc 8, '5.png', #FileSignature");

Retrieve VarBinary Data from SQL and Save the image/file

When I use the SQL statement
SELECT File_Data
FROM Attachments
WHERE UserID = '12345' AND FileNames = 'testing1.jpg'
the image downloads and looks great. But if I put in a stored procedure it creates the file of testing1.jpg in my folder called C:\Testing\ but it is not writing the data in the image and it will not display correctly. Below is what I have to call the stored procedure and to write it up. Any ideas on what I am doing wrong here?
For testing purpose:
strfilename = testing1.jpg
userid = 12345
Code:
protected void LoadFiles(string strfilename, int userid)
{
string fullname = strfilename;
using (SqlConnection cn = new SqlConnection(conn_string))
{
cn.Open();
using (SqlCommand cmd = new SqlCommand("GET_ATTACHMENT", cn))
{
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter p1 = new SqlParameter("#FileName", SqlDbType.NVarChar, 255);
p1.Direction = ParameterDirection.Input;
p1.Value = strfilename;
cmd.Parameters.Add(p1);
SqlParameter p2 = new SqlParameter("#User_ID", SqlDbType.Int);
p2.Direction = ParameterDirection.Input;
p2.Value = userid;
cmd.Parameters.Add(p2);
// Tried using this statement but it did not work. //
SqlParameter pSub = new SqlParameter("#File_Data", SqlDbType.VarBinary);
pSub.Direction = ParameterDirection.ReturnValue;
cmd.Parameters.Add(pSub);
Response.Write(pSub);
// *** *** ///
using (SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
if (dr.Read())
{
// For some reason the data being returned is blank
// When I run it in SQL I get data being returned.
byte[] fileData = (byte[])dr.GetValue(0);
using (System.IO.FileStream fs = new System.IO.FileStream("C:\\Testing\\" + (fullname), System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite))
{
using (System.IO.BinaryWriter bw = new System.IO.BinaryWriter(fs))
{
bw.Write(fileData);
bw.Close();
}
}
}
dr.Close();
}
}
}
}
SQL Server stored procedure:
ALTER PROCEDURE [dbo].[GET_ATTACHMENT]
#User_ID int,
#FileName nvarchar(250)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #FileData varbinary(max)
Set #FileData = (SELECT File_Data FROM Attachments
WHERE UserID = #User_ID and
FileNames = #FileName);
SELECT #FileData
END
A few suggestions:
Set a break point at byte[] fileData = (byte[])dr.GetValue(0); to see if any data is returned before writing it to the file.
Use CommandBehavior.Default
When using CommandBehavior.SequentialAccess try using GetBytes method of SqlDataReader.
As the last resort, change your SP to return User_ID, just to check if anything is returned.

How to call Oracle stored procedure which returns ref cursor

I am trying to call Oracle stored procedure which returns ref cursor, and i need to generate tree view from that returned data. I am new at this and i have two problems.
First problem is that i am not able to call that procedure. I am getting this error: "wrong number or types of arguments in call to 'OBJECT_HIERARCHY'"
And my second problem is that i don't understand how am i gonna get that data when this procedure returns a ref cursor value? There are more then 5000 records in that table and i am not getting that data, but a ref cursor value. Can someone please explain how can i get that data with ref cursor value. I have no experience with Oracle.
This is the procedure definition in oracle:
CREATE OR REPLACE PROCEDURE SAD.object_hierarchy
(nAppId IN NUMBER,
nParentId IN NUMBER DEFAULT -1,
o_cRefCursor OUT SYS_REFCURSOR)
IS
BEGIN
IF NOT o_cRefCursor%ISOPEN THEN
OPEN o_cRefCursor FOR
SELECT
h.PARENT_ID, h.CHILD_ID, h.H_LEVEL,
o.OBJECT_IDENTIFIER, o.OBJECT_TYPE_ID
FROM
(
SELECT
PARENT_ID, CHILD_ID, LEVEL AS H_LEVEL
FROM OBJECT_RELATIONSHIPS
START WITH PARENT_ID = nParentId --> -1 --= 60170
CONNECT BY PRIOR CHILD_ID = PARENT_ID
) h
INNER JOIN
OBJECTS o
ON
o.OBJECT_ID = h.CHILD_ID AND
O.APPLICATION_ID = nAppId;
END IF;
END object_hierarchy;
these are the table field definitions
Column Name Data Type
OBJECT_REL_ID NUMBER (14)
PARENT_ID NUMBER (14)
CHILD_ID NUMBER (14)
OBJECT_IDENTIFIER VARCHAR2 (255 Byte)
OBJECT_TYPE_ID VARCHAR2 (5 Byte)
and this is my code which returns error:
string oradb = "Data Source=(DESCRIPTION="
+ "(ADDRESS=(PROTOCOL=TCP)(HOST=tnt33)(PORT=1521))"
+ "(CONNECT_DATA=(SERVICE_NAME=ORCL)));"
+ "User Id=xxx;Password=xxxxx;";
OracleConnection con = new OracleConnection(oradb);
try
{
con.Open();
OracleCommand cmd = new OracleCommand();
cmd.Connection = con;
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "SAD.object_hierarchy";
cmd.Parameters.Add("nAppId", OracleDbType.Int16).Value = 1;
OracleParameter oraP = new OracleParameter();
oraP.OracleDbType = OracleDbType.RefCursor;
oraP.Direction = System.Data.ParameterDirection.Output;
cmd.Parameters.Add(oraP);
OracleDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
}
reader.Close();
}
catch (Exception ex)
{
con.Close();
}
Can someone please help me and explain to me why is my code returning this error: "wrong number or types of arguments in call to 'OBJECT_HIERARCHY'"
Example:
string connStr = "Data Source=...";
DataSet dataset = new DataSet();
string connStr = ConfigurationManager.ConnectionStrings["OracleConn"].ToString();
using (OracleConnection objConn = new OracleConnection(connStr))
{
OracleCommand cmd = new OracleCommand();
cmd.Connection = objConn;
cmd.CommandText = "Oracle_PkrName.Stored_Proc_Name";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("Emp_id", OracleType.Int32).Value = 3; // Input id
cmd.Parameters.Add("Emp_out", OracleType.Cursor).Direction = ParameterDirection.Output;
try
{
objConn.Open();
cmd.ExecuteNonQuery();
OracleDataAdapter da = new OracleDataAdapter(cmd);
da.Fill(dataset);
}
catch (Exception ex)
{
System.Console.WriteLine("Exception: {0}", ex.ToString());
}
objConn.Close();
}
If you're going to provide the OUT, you'll need to provide nParentId as well because .NET isn't going to name those parameters when the statement is sent to the server.
cmd.Parameters.Add("nParentId", OracleDbType.Int16).Value = -1;

C# insert query not working

i have written insert query for my application to create new user with password, but its not working, please check and correct it.
con.Open();
string a;
a = "insert into tbl_KKSUser(EName,Uname,Password)values(#en,#un,#pas)";
SqlCommand cm = new SqlCommand(a, con);
SqlParameter paramName;
paramName = new SqlParameter("#en", SqlDbType.VarChar, 25);
paramName.Value = DropDownList1.SelectedItem.Text;
cm.Parameters.Add(paramName);
string original = TextBox2.Text.Trim();
int h = original.GetHashCode();
string withHash = original;
b1 = Encoding.BigEndianUnicode.GetBytes(withHash);
encrypted = Convert.ToBase64String(b1);
SqlParameter paramPass;
paramPass = new SqlParameter("#pas", SqlDbType.VarChar, 300);
paramPass.Value = Convert.ToString(encrypted);
cm.Parameters.Add(paramPass);
Response.Write("<script>alert('inserted')</alert>");
con.Close();
You are not executing the query. You need to do:
cm.ExecuteNonQuery();
You must call ExecuteNonQuery function before closing connection
con.Open();
string a;
a = "insert into tbl_KKSUser(EName,Uname,Password)values(#en,#un,#pas)";
SqlCommand cm = new SqlCommand(a, con);
SqlParameter paramName;
paramName = new SqlParameter("#en", SqlDbType.VarChar, 25);
paramName.Value = DropDownList1.SelectedItem.Text;
cm.Parameters.Add(paramName);
string original = TextBox2.Text.Trim();
int h = original.GetHashCode();
string withHash = original;
b1 = Encoding.BigEndianUnicode.GetBytes(withHash);
encrypted = Convert.ToBase64String(b1);
SqlParameter paramPass;
paramPass = new SqlParameter("#pas", SqlDbType.VarChar, 300);
paramPass.Value = Convert.ToString(encrypted);
cm.Parameters.Add(paramPass);
cm.ExecuteNonQuery(); // here call ExecuteNonQuery
Response.Write("<script>alert('inserted')</alert>");
con.Close();
Two things are missing there....
You are passing 3 sql variables in the query and adding only two parameters.
add the following line too,
cm.ExecuteNonQuery();
The ExecuteNonQuery() is one of the most frequently used method in SqlCommand Object, and is used for executing statements that do not return result sets (ie. statements like insert data , update data etc.)
so use
cm.ExecuteNonQuery();
And also add all used parameters i.e. 3 parameters in your example.

Categories