Retrieve C# object from binary that saved in SQL Server database - c#

I want save and retrieve an object from a database. I write C# code to save it as below, and it worked fine. Now I can save an object into the database.
ReportObject ro = new ReportObject()
{
Name = ctrl.Name,
BackColor = ctrl.BackColor,
ForeColor = ctrl.BackColor,
Fonts = ctrl.Font,
TypeofControl = ctrl.GetType()
};
MemoryStream memStream = new MemoryStream();
StreamWriter sw = new StreamWriter(memStream);
sw.Write(ro);
string sql = "INSERT INTO [TemplateDetails] ([Object]) VALUES (#Object)";
SqlCommand cmd = new SqlCommand(sql, con, tran);
cmd.Parameters.Add("#Object", SqlDbType.VarBinary, Int32.MaxValue);
cmd.Parameters["#Object"].Value = memStream.GetBuffer();
cmd.ExecuteNonQuery();
I am already saved a C# object ReportObject in SQL Server database. I want to retrieve it back to a C# object.
string sql = "SELECT [Object] FROM [TemplateDetails]"
SqlDataReader dr = db.Reader(sql);
if (dr.Read())
{
byte[] arrays = (byte[])dr["Object"];
}

I Solved problem myself.
first Serialize to a byte array and save in database.
enter ReportObject ro = new ReportObject()
{
Name = ctrl.Name,
BackColor = ctrl.BackColor,
ForeColor = ctrl.BackColor,
Fonts = ctrl.Font,
TypeofControl = ctrl.GetType()
};
MemoryStream memorystream = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(memorystream, ro);
byte[] yourBytesToDb = memorystream.ToArray();
after retrieving from the database as a byte array. Deserialize and convert to object.
MemoryStream memorystreamd = new MemoryStream(arrBytes);
BinaryFormatter bfd = new BinaryFormatter();
ReportObject deserializedReportObject = bfd.Deserialize(memorystreamd) as ReportObject;

Related

Parameter is not valid when i retrieve Image

string nama = dgGambar1.Rows[e.RowIndex].Cells["nama_gambar"].FormattedValue.ToString();
btnTambahDataBarang.Enabled = false;
koneksi.Open();
MySqlCommand command = new MySqlCommand("SELECT * FROM and_bwi_gambar WHERE nama_gambar = '" + nama + "'", koneksi);
MySqlDataReader rd;
rd = command.ExecuteReader();
while (rd.Read())
{
txtGambar1.Text = rd.GetValue(2).ToString();
byte[] img = (byte[])rd.GetValue(3);
MemoryStream ms = new MemoryStream(img);
pbGambar1.Image = Image.FromStream(ms);
}
koneksi.Close();
when i retrieve an image whose size is more than 250kb, it always get an error 'parameter argument invalid'
There could be 2 options to solve this:
using image converter:
byte[] buffer = (byte[])rd.GetValue(3);
using(var memStream = new MemoryStream(buffer))
{
var ic = new System.Drawing.ImageConverter();
pbGambar1.Image = (System.Drawing.Image)ic.ConvertFrom(stream.ReadAllBytes());
}
or try to load up binary data into memory stream first:
byte[] buffer = (byte[])rd.GetValue(3);
using(var memStream = new MemoryStream(buffer))
{
memStream.Position = 0;
pbGambar1.Image = System.Drawing.Image.FromStream(memStream, false);
}
}

How to retrieve image from database of image datatype to the PhotoBox in c#

The code below is my photo selecting selector (the other button I have in my project is just sending the picArray to the table in the column of image datatype):
private void FileSelectorButton_Click(object sender, EventArgs e)
{
OpenFileDialog ImageSelectorWindow = new OpenFileDialog();
ImageSelectorWindow.Filter = "JPG |*.jpg|PNG |*.png|Bitmap |*.bmp";
ImageSelectorWindow.Title = "Choose an Image";
if (ImageSelectorWindow.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
fileName = ImageSelectorWindow.FileName;
FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
picArray = new byte[fs.Length];
fs.Read(picArray, 0, Convert.ToInt32(fs.Length));
fs.Close();
}
TBFilePath.Text = fileName;
}
Below is my image retrieval code:
SqlCommand cmd2 = new SqlCommand("SELECT avatar FROM Members WHERE Id = '" + value + "'", con);
SqlDataReader dr = cmd2.ExecuteReader();
MemoryStream ms = new MemoryStream((byte[])dr[0]);
PBMemberImage.BackgroundImage = new Bitmap(ms);
This is giving me the following exception:
Can someone help me figure out why?
Retrieve Images from sql server database
Take a look at that and try the code below for retrieving your image. Let me know if that works or not.
byte[] img = (byte[])cmd2.ExecuteScalar();
MemoryStream ms = new MemoryStream();
ms.Write(img, 0, img.Length);
PBMemberImage.BackgroundImage = new Bitmap(ms);

How to make use of memorystream instead of filestream

So what im trying to do is read a Select store procedure from my database save the data in a csv file and make it that the user is able to download it through the web application. I was able to get the requested result by saving the file temporary into my program foldel and using filestream. What i want to do now is skip the part where the file is saved onto my computer and temporary save it in the RAM memory instead. From what i understood i have to make use of memory stream instead of file stream but i dont really understand how i can do that. From what i understood from what i read is that instead of me making use of a file i need to convert my data to bytes make a memorystream out of it and then use it in my FileStreamResult. Am i correct here?
Method when i read from procedure and save to a csvfile:
public static String StoreApproved ()
{
string path1 = HttpRuntime.AppDomainAppPath + "Report.csv";
SqlConnection sqlConnection1 = new SqlConnection("CONNECTIONSTRING");
SqlCommand cmd = new SqlCommand();
SqlDataReader reader;
cmd.CommandText = "ExportApproved";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection = sqlConnection1;
sqlConnection1.Open();
reader = cmd.ExecuteReader();
List<ModelStoreProcedureApproved> TestList = new List<ModelStoreProcedureApproved>();
ModelStoreProcedureApproved test ;
while (reader.Read())
{
test = new ModelStoreProcedureApproved();
// test.Id = int.Parse(reader["IdTimeTracker"].ToString());
test.Month = reader["Month"].ToString();
test.EmailUser = reader["Email"].ToString();
test.Project = reader["Name"].ToString();
test.Approved = reader["Description"].ToString();
test.Month = reader["Month"].ToString();
test.Year = reader["Year"].ToString();
TestList.Add(test);
}
File.Create(path1).Close();
var i = TestList.FirstOrDefault();
using (TextWriter fileReader = new StreamWriter(path1))
{
var csv = new CsvWriter(fileReader);
csv.Configuration.Encoding = Encoding.UTF8;
foreach (var value in TestList)
{
csv.WriteRecord(value);
}
fileReader.Close();
}
sqlConnection1.Close();
return path1;
}
Controller code:
public ActionResult ExportToCSV()
{
string path = Repositories.UserRepository.StoreApproved();
var fileStream = new FileStream(path,
FileMode.Open,
FileAccess.Read);
return new FileStreamResult(fileStream, "text/csv") { FileDownloadName = "export.csv" };
}
Can someone explain me what the best way to do this is?
Other posts i have read
Serialize and Deserialize using BinaryFormatter
BinaryFormatter and Deserialization Complex objects
Using CSVHelper to output stream to browser
You can make it like this:
public static byte[] StoreApproved ()
{
string path1 = HttpRuntime.AppDomainAppPath + "Report.csv";
SqlConnection sqlConnection1 = new SqlConnection("CONNECTIONSTRING");
SqlCommand cmd = new SqlCommand();
SqlDataReader reader;
cmd.CommandText = "ExportApproved";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection = sqlConnection1;
sqlConnection1.Open();
reader = cmd.ExecuteReader();
List<ModelStoreProcedureApproved> TestList = new List<ModelStoreProcedureApproved>();
ModelStoreProcedureApproved test ;
while (reader.Read())
{
test = new ModelStoreProcedureApproved();
// test.Id = int.Parse(reader["IdTimeTracker"].ToString());
test.Month = reader["Month"].ToString();
test.EmailUser = reader["Email"].ToString();
test.Project = reader["Name"].ToString();
test.Approved = reader["Description"].ToString();
test.Month = reader["Month"].ToString();
test.Year = reader["Year"].ToString();
TestList.Add(test);
}
var i = TestList.FirstOrDefault();
var mem = new MemoryStream();
using (TextWriter fileReader = new StreamWriter(mem))
{
var csv = new CsvWriter(fileReader);
csv.Configuration.Encoding = Encoding.UTF8;
foreach (var value in TestList)
{
csv.WriteRecord(value);
}
}
sqlConnection1.Close();
return mem.ToArray();
}
public ActionResult ExportToCSV()
{
byte[] bytes = Repositories.UserRepository.StoreApproved();
Stream stream = new MemoryStream(bytes);
return new FileStreamResult(stream, "text/csv") { FileDownloadName = "export.csv" };
}
I suggest you make clean separation of concerns since you are also using Asp.Net MVC. Instead of reading and creating memory stream inside same method, first read/get the data collection you need and just return the data out of the method. Then inside the action method you can decorate it with required format(binding to UI or returning a file etc.) based on your requirement
Though this is not be a straight answer to your question, and if all that you are looking for is using a memory stream, there are plenty of examples available to use for example as shown here and the answer you accepted etc.
Hope this help you.
using (var ms = new MemoryStream())
{
using (var writer = new StreamWriter(ms))
using (var csv = new CsvWriter(writer))
{
csv.WriteRecords({A list here});
}
ms.ToArray() // here is your actual data in memory stream
}

Binary stream '0' does not contain a valid BinaryHeader error while Deserialization custom object

I faced this error while deserialization a custom object
I am trying to insert a collection of custom class into sql database & retrieve it the insertion going well but retrieving the data & deserialize give me this error
My code sample:
private void InsertObject()
{
ReceiptCollection items = SqlDataRepository.ReceiptProvider.GetAll();
string connectionString = "my connection";
System.Data.SqlClient.SqlConnection connection = new System.Data.SqlClient.SqlConnection(connectionString);
string sql = "INSERT INTO [dbo].[LogHeader]([MasterObject]) VALUES (#MasterObject)";
BinaryFormatter binaryFormatter = new BinaryFormatter();
MemoryStream memoryStream = new MemoryStream();
binaryFormatter.Serialize(memoryStream, items);
using (System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand(sql, connection))
{
byte[] bytes = new byte[memoryStream.Length];
memoryStream.Write(bytes, 0, bytes.Length);
connection.Open();
cmd.Parameters.AddWithValue("#MasterObject", bytes);
cmd.ExecuteNonQuery();
}
}
private void RetrieveObjects()
{
string connectionString = "my connection";
System.Data.SqlClient.SqlConnection connection = new System.Data.SqlClient.SqlConnection(connectionString);
string sql = "Select MasterObject From [dbo].[LogHeader] WHERE LogHeaderID=2";
using (System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand(sql, connection))
{
connection.Open();
byte[] bytes = (byte[])cmd.ExecuteScalar();
BinaryFormatter binaryFormatter = new BinaryFormatter();
MemoryStream memoryStream = new MemoryStream(bytes);
memoryStream.Position = 0;
ReceiptCollection items = (ReceiptCollection)binaryFormatter.Deserialize(memoryStream); // the error happened here
}
}
I was facing the same problem in the serialization and deserialization of a custom class. Everywhere I looked around, they have the same code marked as the solution (as your code presented on the top) but I couldn't make it run correctly. All I was recieving after the memoryStream.Write() method, was an array of zeroes. I changed my code and got it to work.
What I did was (implemented in your code):
BinaryFormatter binaryFormatter = new BinaryFormatter();
MemoryStream memoryStream = new MemoryStream();
binaryFormatter.Serialize(memoryStream, items);
using (System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand(sql, connection))
{
byte[] bytes = new byte[memoryStream.Capacity];
bytes = memoryStream.GetBuffer();
connection.Open();
cmd.Parameters.AddWithValue("#MasterObject", bytes);
cmd.ExecuteNonQuery();
}
This is for sending a byte array to the data base. For retrieving it, I did the following:
connection.Open();
byte[] bytes = (byte[])cmd.ExecuteScalar();
BinaryFormatter binaryFormatter = new BinaryFormatter();
using (MemoryStream memoryStream = new MemoryStream(bytes))
{
memoryStream.Position = 0;
ReceiptCollection items = (ReceiptCollection)binaryFormatter.Deserialize(memoryStream);
}
Try it! It really worked for me.
Start by checking what actually got stored in that column, and also check if the column's type is varbinary or similar. The error suggests that the serialized object's data stream got badly corrupted or truncated. If the row/column does not contain a long "hexstring", then there's a write problem with inserting/updating and search further there.

C# Table Adapter Update Not Working

I am trying to serialize an object to a sql compact database. I am using VCS Express 2008. Every time I run a test to see if my data is sent to the database, nothing is in the database. My code:
string inputForDB = null;
QuizCategoryTableAdapter quizCategoryAdapter = new QuizCategoryTableAdapter();
QuizApp._QuizApp_DataSet.QuizCategoryDataTable quizCategoryTable = new QuizApp._QuizApp_DataSet.QuizCategoryDataTable();
quizCategoryAdapter.Fill(quizCategoryTable);
//Check to see if quizCategory exists
if (quizCategoryTable.Rows.Contains(quizCategory._categoryID)) {
//overwrite (update)
//Serialize the object and put in db
MemoryStream MemStream = new MemoryStream();
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(MemStream, quizCategory);
inputForDB = Convert.ToBase64String(MemStream.ToArray());
quizCategoryAdapter.Insert(quizCategory._categoryName, quizCategory._categoryDescription, inputForDB);
//send update to database
MemStream.Close();
} else {
//append (insert)
MemoryStream MemStream2 = new MemoryStream();
IFormatter formatter2 = new BinaryFormatter();
formatter2.Serialize(MemStream2, quizCategory);
inputForDB = Convert.ToBase64String(MemStream2.ToArray());
quizCategoryAdapter.Insert(quizCategory._categoryName, quizCategory._categoryDescription, inputForDB);
MemStream2.Close();
}
It compiles fine, but for some reason does not work.
You have to call the Adapter Update method as well as AcceptChanges on the DataSet

Categories