Reading binary data from SQL Server CE in C# - c#

I'm trying to read binary data from a SQL Server CE database file.
I tried with this code:
string fileName = "C:\\Users\\Luca\\Desktop\\TestNoah\\TestNoah\\NOAHDatabaseCoreSqlCompact.sdf";
connectionString = string.Format("DataSource='{0}'; Persist Security Info=False", fileName);
using (SqlCeConnection con = new SqlCeConnection(connectionString))
{
con.Open();
using (SqlCeCommand command = new SqlCeCommand("SELECT PublicData FROM Action",con))
{
byte[] barrImg = (byte[])command.ExecuteScalar();
List<byte> test = barrImg.ToList<byte>();
string strfn = Convert.ToString(DateTime.Now.ToFileTime());
FileStream fs = new FileStream("C:\\Users\\Luca\\Desktop\\TestNoah\\TestNoah\\" + strfn + ".jpg" , FileMode.CreateNew, FileAccess.Write);
fs.Write(barrImg, 0, barrImg.Length);
fs.Flush();
fs.Close();
}
}
This code creates an image that I can't open. Any ideas? Thanks to all

The code below uses the ExecuteReader instead of ExecuteScalar (which should not be used unless you expect only a single return value from the result set where your SqlCeCommand has a WHERE limited by primary key or you have TOP 1 in your SELECT.
string targetDir = "C:\\Users\\Luca\\Desktop\\TestNoah\\TestNoah\\";
var reader = command.ExecuteReader();
while (reader.Read())
{
byte[] img = (byte[])reader["PublicData"];
string path = System.IO.Path.Combine(targetDir, string.Format("{0}.jpg", DateTime.Now.ToFileTime()));
System.IO.File.WriteAllBytes(path, img);
}
If you still have image corruption issues, I expect it would be your source data record.

Related

How to Read Image Data (storing word document) from SQL Server Table and save it to local folder

I would like to extract word documents stored as image type fields in SQL and save each individual document in a local folder. The doc files stored in the image type data in sql, are special encoded OLEObjects.
I am trying with one first but I need to do the same for each record in the table. This is what I have done so far:
Byte[] bytData = null;
string constring = #"mystirngconnection";
SqlCommand command = new SqlCommand(#"SELECT LongDescription FROM SuUserReport
WHERE ProductId = 53 AND UserReportId = 31525");
command.CommandType = CommandType.Text;
SqlConnection myconn = new SqlConnection(constring);
command.Connection = myconn;
myconn.Open();
using (SqlDataReader dr = command.ExecuteReader())
{
while (dr.Read())
{
bytData = (byte[])dr["LongDescription"];
}
}
if (bytData != null)
{
FileStream fs = new FileStream("C:\\Temp\\Test1.doc",
FileMode.OpenOrCreate, FileAccess.Write);
BinaryWriter br = new BinaryWriter(fs);
br.Write(bytData, 0, bytData.Length);
fs.Dispose();
}
I basically have two problems:
Reading this type of data it is very slow
Using the code above works for normal word documents however the information in my table has OLEObject encoded information, the code saves a word document but the information is only encoded characters
Previously, these images (word documents) where opened straightaway from SQL when the form was opened using an Access bound object frame linked to the longDescription image type field. The user could edit the document by double clicking on this special frame. The following code opens the document and makes it available to save changes:
With oleLongDescription
.Verb = acOLEVerbOpen 'In a separate window
.Action = acOLEActivate
End With
Could anybody be so kind as to help me out with this, please? I do not mind to use c# or vb as long as it works =).
Here is code that I use to open my blobs. the byte[] myarray is the blob field from the database, the fileext is the extension of the file you are creating and the filename is a name you give it. It deletes any previous file of this name.
public static string Openfilefrombyte(byte[] myarray, string fileext, string filename)
{
Computer myComputer = new Computer();
string filenamef = myComputer.FileSystem.SpecialDirectories.Temp + #"\" + filename + "." + fileext;
if (File.Exists(filenamef))
{
File.Delete(filenamef);
}
//save to file and open
FileStream myfs = new FileStream(filenamef, FileMode.CreateNew);
myfs.Write(myarray, 0, myarray.Length);
myfs.Flush();
myfs.Close();
myfs = null;
Process.Start(filenamef);
return "OK";
}
i basically have two problems:
Reading this type of data it is very slow
Answer : Yes Its Slowly But if You save The Image in sql database as VarBinary it will be Fast .
i am Using OpenFileDialog1 To Bring Image Or what You Want (Rar , Pdf .World ...)
If OpenFileDialog1.ShowDialog = DialogResult.OK Then
Try
T4.Text = OpenFileDialog1.FileName
T5.Text = Path.GetExtension(OpenFileDialog1.FileName)
T7.Text = Path.GetFileNameWithoutExtension(OpenFileDialog1.FileName)
Catch ex As Exception
End Try
End If
Here My Code I used it To Save Data In My Sql database :
Dim SQLCON As New SqlConnection(MyDataBaseCon)
Dim CMD As SqlCommand
Try
CMD = New SqlCommand("Insert Into TBLAtach (ID,AtachName,AtachMain,AtachFile,AtachNM,AtachDT,AtachAdres) Values (#ID,#AtachName,#AtachMain,#AtachFile,#AtachNM,#AtachDT,#AtachAdres)", SQLCON)
SQLCON.Open()
CMD.Parameters.Add(New SqlParameter("#ID", SqlDbType.Int)).Value = Val(T1.Text)
CMD.Parameters.Add(New SqlParameter("#AtachName", SqlDbType.Int)).Value = Val(T2.Text)
CMD.Parameters.Add(New SqlParameter("#AtachMain", SqlDbType.Int)).Value = Val(T3.Text)
Dim FSTream As New FileStream(OpenFileDialog1.FileName, FileMode.Open, FileAccess.Read)
Dim BNStream As New BinaryReader(FSTream)
Dim FAttach() As Byte = BNStream.ReadBytes(BNStream.BaseStream.Length)
CMD.Parameters.Add(New SqlParameter("#AtachFile", SqlDbType.VarBinary)).Value = FAttach
CMD.Parameters.Add(New SqlParameter("#AtachNM", SqlDbType.NVarChar, 50)).Value = T5.Text
CMD.Parameters.Add(New SqlParameter("#AtachDT", SqlDbType.NVarChar, 50)).Value = TD1.Text
CMD.Parameters.Add(New SqlParameter("#AtachAdres", SqlDbType.NVarChar, 250)).Value = T7.Text
CMD.ExecuteNonQuery()
SQLCON.Close()
FSTream.Close()
BNStream.Close()
MsgBox("Ok ", MsgBoxStyle.Information)
SearchID()
ClearTxT()
Catch ex As Exception
MsgBox(ex.Message)
SQLCON.Close()
WaitPic.Visible = False
End Try
Using the code above, saves a word document but the information is only encoded characters
Answer : To retrieve Data (Image,Pdf,RAR,...)
i am Using This Code :
Try
ItDataset.Clear()
Flt = "Select ID , AtachAdres + AtachNM AS 'Fname' , AtachFile from TBLAtach where ID = " & T1.Text & ""
ItDataset = GeneralDataManager.InquireData(ItDataset, Flt, "TBLAtach")
If Me.BindingContext(ItDataset, "TBLAtach").Count > 0 Then
Dim FName As String = ItDataset.Tables("TBLAtach").Rows(0).Item("Fname")
Dim FAttach() As Byte = CType(ItDataset.Tables("TBLAtach").Rows(0).Item("AtachFile"), Byte())
Dim FStream As New FileStream(FName.ToString, FileMode.OpenOrCreate, FileAccess.Write)
FStream.Write(FAttach, 0, (FAttach.Length))
Process.Start(FName)
FStream.Close()
End If
WaitPic.Visible = False
Catch ex As Exception
MsgBox(ex.Message)
End Try
And Change Your Connection To Your Data Base Con Connection
i hope this Answer Is Good For You .
Thank You .

sqlfilestream - getting blob data from SQL Server and saving the file locally to disk

I have the following scenario:
I have successfully saved my files(various extensions) into my sql server db using FILESTREAM. These can be anything from an image, to a word doc, pdf etc.
now i want to retreive them and save them as a file to my local directory.
here is what i have so far
My function calling SQL and getting the the filestream information i want
public static void SelectFile(string sourceId)
{
string serverPath;
string filename;
byte[] serverTxn;
using (TransactionScope ts = new TransactionScope())
{
using (SqlConnection conn = new SqlConnection(ConfigurationManager.AppSettings["DBConn"].ToString()))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("OPS.LoadFileBlobFromSQL", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#AttachmentId", SqlDbType.VarChar).Value = sourceId;
using (SqlDataReader rdr = cmd.ExecuteReader())
{
rdr.Read();
filename = rdr.GetSqlString(0).Value;
serverPath = rdr.GetSqlString(1).Value;
serverTxn = rdr.GetSqlBinary(2).Value;
rdr.Close();
}
}
StreamObjectFromFilestream(serverPath, serverTxn, filename);
}
ts.Complete();
}
}
private static void StreamObjectFromFilestream(string serverPath, byte[] serverTxn, string filename)
{
SqlFileStream sfs = new SqlFileStream(serverPath, serverTxn, FileAccess.Read);
byte[] buffer = new byte[sfs.Length];
sfs.Read(buffer, 0, buffer.Length);
System.IO.File.WriteAllBytes(#"c:\test\hello.pdf", buffer);
sfs.Close();
}
I am getting serverpath, filename and serverTxn .. but when i go into my StreamObjectFromFilestream function the buffer is empty.. i know i am missing something simple here ... just dont know what.
Any pointers in the right direction would be appreciated.
Thanks,
Corey
You can skip using the SqlFilestream inside StreamObjectFromFilestram, your serverTxn is already a byte array that the Method WriteAllBytes is needing.

Reading large text files into SQL Server stored procedure

I've got to read and put text into a SQL Server table.
I initially started with a BULK INSERT, but I have the problem that I don't now the encoding of the files and so the BULK sometimes outputs some errors.
Then, I choose to make through a C# Console Aplication, and everything works fine, except when I have large files. To about 300-400 MB, I don't have any problem, but above that, I'm getting a OOM error.
Here's my code:
static void Main()
{
string fullFileName = #"C:\Temp\410.4604";
string FileName = System.IO.Path.GetFileName(fullFileName);
string table = FileName.Substring(0, 3);
Console.WriteLine("Iniciou às: " + inicio);
DataTable data = new DataTable();
data.Clear();
data.Columns.Add("Text");
using (System.IO.FileStream fs = System.IO.File.Open(fullFileName, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read))
using (System.IO.BufferedStream bs = new System.IO.BufferedStream(fs))
using (StreamReader sr = new StreamReader(bs))
{
string line;
while ((line = sr.ReadLine()) != null)
{
data.Rows.Add(line);
}
}
var conn = new System.Data.SqlClient.SqlConnection(myConn);
SqlCommand insertCommand = new SqlCommand(myProc, conn);
insertCommand.CommandTimeout = 0;
insertCommand.CommandType = CommandType.StoredProcedure;
SqlParameter insParam1 = insertCommand.Parameters.AddWithValue("#data", data);
insParam1.SqlDbType = SqlDbType.Structured;
SqlParameter insParam2 = insertCommand.Parameters.AddWithValue("#table", table);
conn.Open();
insertCommand.ExecuteNonQuery();
conn.Close();
data.Clear();
data = null;
GC.Collect();
Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
}
Any ideas? Or advices to improve this?
Many thanks

Issue while inserting images to the mysql database

I am trying to insert an image from windows application to mysql database , it has been executed succesfully but there exists no data in my table.
Here I have used the following code. The execution is successful, according to my table email id and image must must be stored in table , but both the fields are saved as empty.
public void LoadImages()
{
MySqlConnection cn = new MySqlConnection(connstring);
cn.Open();
string image = txtLogo.Text;
byte[] ImageData;
FileStream fs = new FileStream(image, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
ImageData = BitConverter.GetBytes(fs.Length);
br.Close();
fs.Close();
MySqlParameter parImage = new MySqlParameter();
parImage.ParameterName = "?Images";
MySqlCommand cmd = new MySqlCommand("insert into Fn_Pictures(Images,Email)values(?Images,'" + txtEmailIdText + "')", cn);
parImage.MySqlDbType = MySqlDbType.MediumBlob;
parImage.Size = 3000000;
parImage.Value = ImageData;//here you should put your byte []
cmd.Parameters.Add(parImage);
cmd.ExecuteNonQuery();
cn.Close();
}
BitConverter.GetBytes(fs.Length);
This returns the length as a byte[4], not reads the image data.
Take a look here for reading the file:
http://msdn.microsoft.com/en-us/library/system.io.file.readallbytes(v=vs.110).aspx
You probably also want to set parImage.Size to ImageData.length, not 3000000.

Pass file name from file upload control to filestream

SqlConnection conn = new SqlConnection("Data Source=DDPRO8-WIN7X86\\SQLEXPRESS;Initial Catalog=mp3bytes;Persist Security Info=True;Integrated security=true; User ID=; Password=;");
SqlCommand cmd = null;
SqlParameter param = null;
cmd = new SqlCommand(" INSERT INTO mp3_bytes (songs) " + " Values (#songs) ", conn);
FileStream fs = null;
string path = fileUpload.FileName;
fs = new FileStream(path, FileMode.Open, FileAccess.Read);
Byte[] song = new Byte[fs.Length];
fs.Read(song, 0, song.Length);
fs.Close();
param = new SqlParameter("#songs", SqlDbType.VarBinary, song.Length, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, song);
cmd.Parameters.Add(param);
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
where fileUpload is the file upload control. I am uploading an mp3 file.
When I execute this I'm getting could not find file '', how can I pass the uploaded filename to filestream from upload file control?
Use fileUpload.PostedFile.FileName
Also its better to check if there is any file that has been uploaded using fileUpload.HasFile property. You can also guard against zero length files by checking against fileUpload.PostedFile.ContentLength > 0.
Edit: just realized your mistake
The uploaded file content needs to saved by you on the disk using fileUpload.PostedFile.SaveAs method. The above file name property will give you file name on the client machine, but the file will not exist on the server. You need to save it wherever you want on server. For example,
var path = Path.Combine(tempDirectory, fileUpload.PostedFile.FileNam);
fileUpload.PostedFile.SaveAs(path);
This would put the uploaded file in the temp directory on the server. You can also use PostedFile.InputStream to read file contents.
fs = new FileStream(path, FileMode.Open, FileAccess.Read); will never work as file does not exist on web server machine.
Edit: based on your sample code
Remove FileStream fs = null; and replace
fs = new FileStream(path, FileMode.Open, FileAccess.Read);
with
var fs = uploadFile.PostedFile.InputStream;
and that should do the trick.
If you really do need to use a FileStream, then you'll need to set the FileMode to Create rather than Open as you're not Opening a file, you're Creating one.
fs = new FileStream(path, FileMode.Create);
EDIT: But, as VinayC says, SaveAs() does all the hard work for you!
EDIT: It looks like you are trying to save the file to disk, then read the bytes from the file to pass to sql. You can bypass that saving / reading part by just getting FileBytes from the FileUpload control.
SqlConnection conn = new SqlConnection("Data Source=DDPRO8-WIN7X86\\SQLEXPRESS;Initial Catalog=mp3bytes;Persist Security Info=True;Integrated security=true; User ID=; Password=;");
SqlCommand cmd = null;
SqlParameter param = null;
cmd = new SqlCommand(" INSERT INTO mp3_bytes (songs) " + " Values (#songs) ", conn);
param = new SqlParameter("#songs", SqlDbType.VarBinary, fileUpload.FileBytes.Length, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, fileUpload.FileBytes);
cmd.Parameters.Add(param);
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();

Categories

Resources