Saving reference to a blob type - c#

I want to save a reference to an image that will be stored in the database.
But I am not sure how to approach this in C# (Entityframework).
Using EF's code first approach.
In the Model class, must i do String imageReference, og must I use byte? Or is there another and better solution to this? What I want once the database is created, for that column, it should say Blob or what ever is used to hold large objects like images.
I am also thinking that only saving a reference in the database, instead of the image itself might be a solution. But I don't know which is better?

You need to create it as a byte, and your db should be blob
var image = new ImageEntity(){
imageReference= convertImageToByteArray(image)
}
_Context.Images.Add(image);
_Context.SaveChanges();
Convert ur image to a byte array:
public byte[] convertImageToByteArray(Image imageIn)
{
MemoryStream memStream = new MemoryStream();
imageIn.Save(memStream , ImageFormat.Gif); //u may choose other formats
return memStream .ToArray();
}
I would recommend saving the file path as reference instead of storing it as a blob unless you have no choice. This is because a larger DB will degrade the performance, the hard disk would do a better job at handling files. If your image files are larger than 1MB, the file system has an advantage over a SQL Server. Also storing it in the file system has greater flexibility (i.e. you may migrate your files elsewhere next time, and change the link in the DB during migration, you can't do that on the DB)

Related

Retrieve and Place Image From SQL Db to a PictureBox In C# WinFormApp

I want to save and retrieve an image from database and place it in a picturebox in my windows form application.
Does any one have any code for it? and please tell me the data type in SQL that I have to use for storing my image (which one is better, Varbinary(MAX) or Image?)
this is the code i'm using for taking the image from a PicturBox and making it into a binary and storing it into a Varbinary(MAX) in the Database and when I Run The code It says: Implicit conversion from data type varchar to varbinary(max) is not allowed. Use the CONVERT function to run this query.
System.IO.MemoryStream mymemory = new System.IO.MemoryStream();
img.Save(mymemory,Pbox.Image.RawFormat);
Byte[] myarray = mymemory.GetBuffer();
What should I do?
If anyone has better code please help me with copying the code here for me
any help will be appreciated.
Based on your prior "connection strings" question, the best answer would be to not save the image in that table, only a reference to it; either by using a filestream table or by a text field containing the file system location.

Right way to store Image in database through Entity Framework

I have converted an image to a byte array using below code to store it in Database
if (Request.Content.IsMimeMultipartContent())
{
var provider = new MultipartMemoryStreamProvider();
await Request.Content.ReadAsMultipartAsync(provider);
foreach (var file in provider.Contents)
{
var filename = file.Headers.ContentDisposition.FileName.Trim('\"');
var attachmentData = new AttachmentData ();
attachmentData.File = file.ReadAsByteArrayAsync().Result;
db.AttachmentData.Add(attachmentData);
db.SaveChanges();
return Ok(attachmentData);
}
}
Here File column in DB is of type "varbinary(max)" and in EF model it is byte array (byte[]).
Using above code I was able to save the image in the File column something similar to "0x30783839353034453437304430413143136303832....." (This length is exceeding 43679 characters which is more than default given to any column so the data got truncated while storing it)
I have to change the default length(43679) of column to store it in database.
Am I doing it the correct way to retrieve and store image in Database. I was also thinking to store the image as "Base64 String" but 43679 will still exceed.
I am using Angular JS to show the image on front end which uses WebAPI to fetch and save the image as ByteArray in database.
Yes, It really helps to not know how databases work.
First:
varbinary(max)
This stores up to 2gb, not 43679 bytes.
Then:
similar to "0x30783839353034453437304430413143136303832.....
This is not how it is stored. This is a textual representation in uotput.
(This length is exceeding 43679 characters which is more than default given to
any column so the data got truncated while storing it)
There is no default given to any column - outside basically SQL Server Management Studio which likely will not be able to handle images as images and has a lot of limitations. But this is not the database, it is an admin ui.
I was also thinking to store the image as "Base64 String" but 43679 will still
exceed.
Actually no, it will exceed this by more - your data will be significantly longer as Base64 is longer than binary data.

Entity Framework and appending VARBINARY field

i am trying to add bytes of a file to a field in the database which is of type VARBINARY bu this needs to be appended due to file size constraits
Is there any example code/website of how to do this? Or is it even possible to append the bytes to this field using Entity Framework?
I need to append the data as getting a byte array of 1GB + is going to cause memory exceptions so I think this is the only way..
Some code I have done
using (var stream = File.OpenRead(fn))
{
long bytesToRead = 1;
byte[] buffer = new byte[bytesToRead];
while (stream.Read(buffer, 0, buffer.Length) > 0)
{
Item = buffer;
}
}
Thanks for any help
The basic idea is making an stored procedure that implements an update like this:
UPDATE MyTable SET Col = Col + #newdata WHERE Id = #Id
and invoking it using ExecuteSqlCommand (see MSDN docs here).
But in this case you're only transfering the problem to the SQL Server side The column must be retrieved, modified, and written back).
To really get rid of the memory problem, implement your stored procedure using UPDATETEXT, which is much more efficient for your requirements:
Updates an existing text, ntext, or image field. Use UPDATETEXT to change only a part of a text, ntext, or image column in place. Use WRITETEXT to update and replace a whole text, ntext, or image field
When storing large files in a database, it is usual to store the file on disc on the Web Server rather than in the database. In the database you store the path to the file, thus your code can get to it's contents without having to store gigs of data in the database.
However, if you are attempting to manipulate the contents of a 1GB+ file in memory, this is going to be interesting however you do it...

Getting a blob size without the blob itself

I have a table that has a blob column representing a file.
I'd like to run a LinqToSql query that returns a name and description of the file, along with the file size... but in the interests of not killing performance, I obviously don't want to download the whole blob!
var q = from f in MyFiles
select new {f.Name, f.Description, f.Blob.Length};
appears to pull the entire blob from the DB, then calculate its length in local memory.
How can I do this so that I only get the blob size, without downloading the entire blob?
I think the best choose in your case is to store blob size in the separate column, when storing file to database.

C# Storage of User Entered Data

I'm trying to write a C# program, where when a user enters some data into a text box and clicks on a "save" button, the information is stored in some sort of file that when the program is opened the next time around, the information is automatically loaded in.
I'm using Visual C# express. What's the best way to do this without requiring some sort of database like MySQL or MSSQL or Access?
If the only way or easiest way is a database, I'd rather use Access. If so, does the user of the program need Access installed for my program to run on their computer? What if I go with another database?
p.s.
I forgot to mention, I'd rather the user not be able to access this file and read the contents easily. Text file without encryption would be easy to open. Any way to encrypt this? Also, if I use a delimiter like ':', then that means the user cannot use that character. So any other way?
Thanks!
Make your user data serializable by adding the keyword:
[Serializable]
above your data structure. When you load the dialog box, load your serialized structure from disk, and when you leave the dialog, save the data structure.
From a style standpoint, you should probably not have the dialog box change data until the dialog box is closed (if it's modal).
To save:
private bool Save(String inFileName, MyObject inObject){
try {
FileStream theStream = File.Open(inFileName, FileMode.Create);
BinaryFormatter theFormatter = new BinaryFormatter();
theFormatter.Serialize(theStream, inObject);//add it to the end there
theStream.Dispose();
theStream.Close();
} catch{
return false;
}
return true;
}
To Load:
private MyObject Read(String inFileName){
MyObject theReturn = null;
try {
FileStream theStream = File.Open(inFileName, FileMode.Open, FileAccess.Read);
BinaryFormatter theFormatter = new BinaryFormatter();
theReturn = (CImageData)theFormatter.Deserialize(theStream);//add it to the end there
theStream.Dispose();
theStream.Close();
}
catch {
return null;
}
return theReturn;
}
You can also use 'using' on a stream, but this code is pretty straightforward, I think. It also means that you can add more items into MyObject.
Edit: For encryption, you can add in AES or something similar. That might be overkill for you, and saving the file as binary may make it readable by something like notepad, but not easily editable. Here's a lengthy explanation on real encryption:
http://msdn.microsoft.com/en-us/magazine/cc164055.aspx
Sql Compact Edition would hide the data from being easily accessible (and its free). You can also password protect a CE database. A SQL CE database is contained completely in an .SDF file, like Access, so you can copy the .sdf file around and not have to worry about network connectivity, etc.
If your application is only to be used by a single person then simply store your data in a file (XML would give you some structure)
If your application will be used by multiple people and the data shared among them, then a database is your best option. If you use a database then yes you will need to have a database installed on your users computer, though it is possible to do that transparantly to your user, for that you are best off with an embeddable database, something like MySQL would be your best bet.
(EDIT: the database actually does not have to be on the users computer, but he would need to be able to see it from his coputer)
If it's very simple then you could place it in a plain text file. For more structured data you could consider storing it as a CSV and parsing it or creating an XmlDocument and saving that to disk.

Categories

Resources