'Invalid Parameter' when downloading data from sql server - c#

First of all I'm using a FileStream with the server. The server is SQL Server express 2014.
I configured the database and table correctly (I hope) and I was able to upload an image as a varbinary, but when I try to download that image I get an error
An invalid parameter was passed to the function.
Here is the database structure
Records(
[id] [uniqueidentifier] ROWGUIDCOL NOT NULL UNIQUE,
[Name] [varchar](64) NULL,
[Clip] [varbinary](max) FILESTREAM NULL,
)
And the code for downloading the image
private object GetTransactionContext()
{
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "SELECT GET_FILESTREAM_TRANSACTION_CONTEXT()";
cmd.CommandType = CommandType.Text;
cmd.Connection = sql_Connection;
return cmd.ExecuteScalar();
}
private void BeginTransaction()
{
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "BEGIN TRANSACTION";
cmd.CommandType = CommandType.Text;
cmd.Connection = sql_Connection;
cmd.ExecuteScalar();
}
private void CommitTransaction()
{
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "COMMIT TRANSACTION";
cmd.CommandType = CommandType.Text;
cmd.Connection = sql_Connection;
cmd.ExecuteScalar();
}
//Command for reading the data
public async void ReadFromDatabase(string Name)
{
//enter the command parameter
sql_Command_Read.Parameters.Add("#Name", SqlDbType.VarChar).Value = Name;
//open a connection to the server
sql_Connection.Open();
this.BeginTransaction();
//get the path to the BLOB object
string filePath = null;
Object pathObj = sql_Command_Read.ExecuteScalar();
if (DBNull.Value != pathObj)
{
filePath = (string)pathObj;
}
else
{
throw new NotImplementedException();
}
Object obj = this.GetTransactionContext();
byte[] sql_TransactionToken = (byte[])obj;
sql_FileStream = new SqlFileStream(filePath, sql_TransactionToken, FileAccess.ReadWrite, FileOptions.SequentialScan, 0);
byte[] buffer = new byte[(int)sql_FileStream.Length];
sql_FileStream.Seek(0L, SeekOrigin.Begin);
sql_FileStream.Read(buffer, 0, buffer.Length);
File.WriteAllBytes("C:\test.mp4", buffer);
this.CommitTransaction();
}
The content of the command is
sql_Command_Read.CommandText = "SELECT Picture.PathName() FROM Archive.dbo.Records WHERE Name = #Name";
Again I am new to database and sql client programming. Now about the code. The error that I get is on this line:
sql_FileStream = new SqlFileStream(filePath, sql_TransactionToken, FileAccess.ReadWrite, FileOptions.SequentialScan, 0);
and about the parameters here are the values they get:
filePath = "\\\\LAPTOP-PC\\VIDEOPRESENTERDB\\v02-A60EC2F8-2B24-11DF-9CC3-AF2E56D89593\\Archive\\dbo\\Records\\Picture\\C94D4189-9ECF-448B-B05A-ABF9331BF6CE\\VolumeHint-HarddiskVolume2"
obj has 16 numbers ranging from 0 to 255.
I am obviously making a mistake somewhere but I don't know where exactly

Related

Sql reader returning DBnull for every row

I am trying to display pictures from my SQLSEVER database on my website. My users have a picture field with a picture datatype. If the picture column is null, then I want the picture displayed to be a egg.jpg, but right now for every person their picture is egg.jpg, even if they have a picture in the database. Here is my method.
public string getImageUrl()
{
System.Data.SqlClient.SqlConnection sc = new System.Data.SqlClient.SqlConnection();
sc.ConnectionString = "Server =MRCOMPUTER2\\SQLEXPRESS; Database = WBL;Trusted_Connection=Yes;";
sc.Open();
System.Data.SqlClient.SqlCommand insert = new System.Data.SqlClient.SqlCommand();
insert.Connection = sc;
insert.CommandText = "SELECT profilePicture from SystemUser";
insert.ExecuteNonQuery();
SqlDataReader reader = insert.ExecuteReader();
string url = "";
while (reader.Read())
{
if ( !DBNull.Value.Equals(reader[0]))
{
url = "data:Image / png; base64," + Convert.ToBase64String((byte[])reader[0]);
}
else {
url = "images/egg.jpg";
}
}
return url;
}
Your code returns the image for the last user in your table.
Here:
insert.CommandText = "SELECT profilePicture from SystemUser";
you select all users from the table (not just the one you currently show). Then:
while (reader.Read())
{
...
url = ...
...
}
you re-assign url inside every iteration of your while loop. This is semantically equivalent to:
url = ... /* The value determined from the last record of the reader. */
Thus, all your users show the same image - the one of the last user in your table.
You SELECT statement is attached into a ExecuteNonQuery?
Take it off.
Just perform the READER statement...
Try this:
static void Main(string[] args)
{
string connectionString = "Server=.;Database=AA;Trusted_Connection=True;";
/*
CREATE TABLE [dbo].[SystemUser]
(
[ProfilePicture] [varbinary](max) NULL
)
*/
using (SqlConnection connection = new SqlConnection(connectionString))
{
string sql = #"
INSERT [AA].[dbo].[SystemUser] ([ProfilePicture]) VALUES (#ProfilePicture);
INSERT [AA].[dbo].[SystemUser] ([ProfilePicture]) VALUES (NULL);
";
SqlCommand command = new SqlCommand();
command.Connection = connection;
command.CommandText = sql;
command.CommandType = CommandType.Text;
byte[] bytes = File.ReadAllBytes(#"1.jpg");
command.Parameters.AddWithValue("#ProfilePicture", bytes);
connection.Open();
command.ExecuteNonQuery();
}
DataSet ds = new DataSet();
using (SqlConnection connection = new SqlConnection(connectionString))
{
string sql = #"
SELECT TOP 1000 [ProfilePicture] FROM [AA].[dbo].[SystemUser];
";
SqlCommand command = new SqlCommand();
command.Connection = connection;
command.CommandText = sql;
command.CommandType = CommandType.Text;
connection.Open();
SqlDataAdapter da = new SqlDataAdapter(command);
da.Fill(ds);
}
var rows = ds.Tables[0].Rows.Cast<DataRow>();
foreach (DataRow row in rows)
{
byte[] bytes = row.Field<byte[]>(0);
if (bytes != null)
{
string fileName = Guid.NewGuid().ToString("N") + ".jpg";
File.WriteAllBytes(fileName, bytes);
}
}
}
Can you try using the name of the column such as
var Val = (String)reader["column name"];
Also, try something like this to test:
while (reader.Read())
{
var testVal = reader.GetString(0);
Var testVal2 = reader.GetString(1);

Binary data displayed instead of image in c# and mysql

public void ProcessRequest(HttpContext context)
{
MySqlConnection con = new MySqlConnection(ConfigurationManager.ConnectionStrings["ConString"].ConnectionString.ToString());
// Create SQL Command
int adid= int.Parse(context.Request.QueryString["adid"]);
int imgid = int.Parse(context.Request.QueryString["imgid"]);
MySqlCommand cmd = new MySqlCommand();
//cmd.CommandText = "Select i.image_id, i.image_name, i.image_byteImage, i.image_adId from images i,postadverties p where i.image_adId =#ID";
cmd.CommandText = "SELECT image_id,image_byteImage FROM images WHERE image_adId="+ adid + " and image_id="+ imgid;
cmd.CommandType = System.Data.CommandType.Text;
cmd.Connection = con;
//MySqlParameter AdId = new MySqlParameter("#ID", MySqlDbType.Int32);
//MySqlParameter imgid = new MySqlParameter("#imgid", MySqlDbType.Int32);
//AdId.Value =
//imgid.Value =
//cmd.Parameters.Add(AdId);
//cmd.Parameters.Add(imgid);
con.Open();
MySqlDataReader dReader = cmd.ExecuteReader();
if (dReader.Read())
{
byte[] binaryimg = (byte[])dReader["image_byteImage"];
string base64string = "data:image/jpeg;base64," + Convert.ToBase64String(binaryimg);
context.Response.Write(base64string);
context.Response.Flush();
context.Response.End();
}
dReader.Close();
con.Close();
}
Click here to see result
When trying to display images stored in database above result is displayed instead of image.No clue why this issue is coming.Is there any problem while converting it or some else.In another page it works and on some pages it does not.

Insert and read blob "pdf files" in oracle database with C#

I want to insert and read pdf blop to oracle with c#.I tried to do something below.I need insert oracle blop pdf file with C#.I am using this code
var fs = new FileStream(txtFileName.Text, FileMode.Open, FileAccess.Read);
var blobByte = new byte[fs.Length];
fs.Read(blobByte, 0, Convert.ToInt32(fs.Length));
fs.Close();
id=nextÄ°d("tablename")//take ID_SEQ.NEXTVAL
var con = new racleConnection(System.Configuration.ConfigurationSettings.AppSettings["Orclsys"]);
var cmd = new OracleCommand();
con.Open();
cmd.Connection = con;
cmd.CommandText = "INSERT INTO tablename values(:id,:blopfile )";
OracleTransaction sqlTrans = con.BeginTransaction();
cmd.Transaction = sqlTrans;
try
{
cmd.Parameters.Clear();
cmd.Parameters.AddWithValue(":id", Id);
var blobParameter = new OracleParameter();
blobParameter.OracleType = OracleType.Blob;
blobParameter.ParameterName = ":blopfile ";
blobParameter.Value = blobByte;
cmd.Parameters.Add(blobParameter);
cmd.ExecuteNonQuery();
Result = true;
sqlTrans.Commit();
}
catch(Exception ex)
{
}
finally
{
con.Close();
con.Dispose();
sqlTrans.Dispose();
cmd.Dispose();
}
so I want read this file from db and i am starting code but I can not continue.
How can I continue after.could you help me.!!
try
{
orcl.Connect(DbUser.System);
orcl.CommandText = "SELECT blopfile FROM tablename WHERE id= :id";
orcl.ClearParameters();
orcl.AddParameter(":id", id);
orcl.ExecuteDataReader();
var lob = orcl.DataReader.GetOracleLob(0);
var pdffile= new Bitmap(lob);
//
//how can I continue code here....
//
}
catch(Exception ex)
{
}

How to convert Inline SQL to a stored procedure in SQL Server

My code shown below is create as an inline SQL statement. How can this code be written as a stored procedure??
The code is:
public Stream SelectEmployeeImageByID(int theID)
{
SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString.ToString());
string sql = "SELECT Image FROM Employees WHERE EmployeeId = #EmployeeId";
SqlCommand cmd = new SqlCommand(sql, connection);
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("#EmployeeId", theID);
connection.Open();
object theImg = cmd.ExecuteScalar();
try
{
return new MemoryStream((byte[])theImg);
}
catch
{
return null;
}
finally
{
connection.Close();
}
}
you can do this
create procedure SelectEmployeeImage(#employee int)
as
begin
SELECT Image FROM Employees WHERE EmployeeId = #EmployeeId
end
then your code will be this form
public Stream SelectEmployeeImageByID(int theID)
{
SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString.ToString());
string sql = "SelectEmployeeImage";
SqlCommand cmd = new SqlCommand(sql, connection);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#EmployeeId", theID);
connection.Open();
object theImg = cmd.ExecuteScalar();
try
{
return new MemoryStream((byte[])theImg);
}
catch
{
return null;
}
finally
{
connection.Close();
}
}
hope this will help you
Creating Stored Procedure
Create procedure SP_InsertEmployee
as
#EmployeeId int
BEGIN
SELECT Image FROM Employees WHERE EmployeeId=#EmployeeId
END
You Should Set CommandType=StoredProcedure and Rest of will be same
cmd.CommandType = CommandType.StoredProcedure;
Recommendations
Always use using which automatically disposes connections
using (SqlConnection con = new SqlConnection())
{
con.open();
using (SqlCommand cmd = new SqlCommand(sql, connection))
{
//object theImg = cmd.ExecuteScalar();
}
con.Dispose();
}

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.

Categories