In my database I have stored images in the "image" data type, showing up as a binary code.
I now want to retrieve all images from one column and diplay them on a asp.net page with C#.
databaseDataContext db = new databaseDataContext();
var images = from Picture p in db.Pictures
select p.pictureThumb;
then I use this:
foreach (Picture p in images)
{
galleryImages.Controls.Add(p);
}
But that doesn't work because Binary can't be converted to Picture. I have Googled this and found that I have to cast to Byte and then to image? I can't find examples on how to do that though.
This should do it:
databaseDataContext db = new databaseDataContext();
var images = from p in db.Pictures
select Image.FromStream(new MemoryStream(p.pictureThumb.ToArray());
foreach (Image image in images)
{
galleryImages.Controls.Add(image);
}
Note that Image.FromStream takes ownership of the stream - it's only a MemoryStream anyway, but do make sure that you dispose of the image, for various reasons.
EDIT: Ah... I hadn't realised that this was for ASP.NET. That makes things harder - because the HTML is going to contain URLs, and then you'll need to be able to fetch the data later.
Does a picture have an ID of some kind? If so, fetch that instead of the actual data, and then set up a URL which is able to serve any thumbnail based on the ID (by fetching it from the database and just serving it with an appropriate content type).
Related
I am learning C# including interacting with SQL Server databases. I am stuck however, on adding PictureBox images programmatically to a SQL Server database:
I have created a form with text fields, a picture box, to display/edit/add single records to a database successfully and am successfully using all of the following:
DB Connection = RRConnection
SqlCommand object = playersCommand
SqlDataAdapter object = playersAdapter
dataTable object = playersTable
currencyManager = playerManager
PictureBox1 control = including a button to navigate filesystem and select/load jpeg image into form PictureBox1
Bindings like - txtName.DataBindings.Add("Text", playersTable, "Name") for text fields - I think I need to bind the picturebox1 IMage Byte Array but do not know how to do
When the form closes, the table is loaded into the SQLServer database table tbl_BB into the column named "Image" of type image.
I know I have to convert the image to a byte array to save, but am confused on how to bind the image byte array to the dataTable, allowing it to be uploaded to the database on form close. I've done a lot of googling on it but the solutions do not seem to match the code I am using...
Given the above, can you advise the code necessary for this?
Don't use image it will be removed from MS SQL soon.
https://learn.microsoft.com/en-us/sql/t-sql/data-types/ntext-text-and-image-transact-sql
Just use varbinary.
the general way to do it is:
1) SQL Server will have a varbinary(max) column.
2) Take the jpeg and convert it to a byte array
3) add the byte array as a paramter to your sql command object
4) execute nonquery for insertion.
May I suggest you merely save the image on disk directly, and reference the path to the image in the DB instead? Saving images in a db is considered bad practice.
I'm using C# 4.5 Framework and MySql
MySqlDataReader reader = Command.ExecuteReader();
if (reader.Read())
{
byte[] ReturnImage = reader["Photo"] as byte[];
MemoryStream ms = new MemoryStream(ReturnImage);
Image Photo = Image.FromStream(ms); //Error is in this statement!!
}
When this stmt is executed the following error displays "Parameter is not valid"
I couldn't find the answer from the web.. Somebody Pls help..
The most likely cause here is that the contents of the longblob are not the raw image bytes. Rather than go around in circles, the first thing to do is to: compare them. For example, you say (comments) that the data came from a jpg file, via OpenFileDialog. In that case, compare them. Check that you have successfully stored and retrieved the image.
Let's suppose that the file in question is c:\Some\Photo.jpg - stored etc per whatever process. In that case, you should be able to check the contents are the same. Until the following reports success, all bets are off:
byte[] original = File.ReadAllBytes(#"c:\Some\Photo.jpg");
byte[] ReturnImage = reader["Photo"] as byte[];
if(Convert.ToBase64String(original) == Convert.ToBase64String(ReturnImage)) {
Console.WriteLine("Success; the contents match");
} else {
Console.WriteLine("Failure; the contents are different");
}
If this reports "Failure; the contents are different", then the error is most likely in one of:
the code where you prepare the image to be stored (populating parameters etc)
the stored procedure that does the storage
the code that fetches the image back from the database
If this reports "Success; the contents match": then and only then is it meaningful to look at the code that attempts to load the Image. In this scenario, and assuming that c:\Some\Photo.jpg loads in most other image loading tools ("paint", etc) - then it is possible that Image doesn't recognise the subformat. But my guess is that it is going to say "Failure; the contents are different".
Note that Convert.ToBase64String here is used solely as a lazy way to check binary equivalence. You wouldn't use it like this in production code, but it is fine for this purpose.
I am creating a asp.net app in C# .net 4.0 using VS 2008 & MS SQL Server 2008 R2. I want to upload image(.bmp) for each order and store it in DB corresponding to its order. It must be retrieved when View functionally is requested.
My requirement is to store images and retrieve it. Number of orders might be around 50 orders each day. It might be over be overhead as number increases. Please suggest me efficient method to overcome memory issue.
Well, you can either store them in the database as varbinary(max) or store a URL to a file. If you have 50 images a day, it might be better to go for the file and URL method.
There's advantages and disadvantages to both. But as you said you want to store them in the DB:
I think one big one on the database storage is that no one can just come along and rename / delete the folder, or mess with the files in it.
Another good point for the database is that you can restore a database and not have to try to keep the keep the folder in sync.
You can use an ImageConverter to convert between an array of bytes to an image and back
var stream = new MemoryStream();
var imageData = DataAccess.GetImageData(); //Returns a System.Linq.Binary for me
var imgageBinaryData = imageData.ImageData.ToArray(); //This returns a byte array
var img = Image.FromStream(stream); //Here is your image ready for displaying
Then to go back something like
var stream = new MemoryStream();
img.Save(stream,System.Drawing.Imaging.ImageFormat.Jpeg);
var myBytes = ms.ToArray();
Edit: Oh and storing them as Jpeg rather than Bmp will save a lotta space
I have some simple entity which now needs to have a Profile image. What is the proper way to do this? So, it is 1 to 1 relationship, one image is related only to one entity and vice versa. This image should be uploaded through webform together with inserting related entity.
If anyone can point me to the right direction how to persist images to the db and related entity will be great.
Just a side comment: I think is not a good idea to store images in db.
In general is not a good idea store images in db as dbs are designed to store text not big binary chunks. Is much better to store paths for images and have images in a folder. If you want to get sure of 1 to 1 relationship name image with ID of entity (1323.jpg).
If you want to have image paths you should follow some guidelines (In general code defensively):
On upload of image check that image is valid (even made a binary check of image header)
Don't allow to overwrite an existing image in case of a INSERT of a new entity.
Name images as primary key (1.jpg, 2.jpg)
On load of image don't assume that image is going to be there.
Do not allow (if possible) manual interaction with images (No remoting in machine and copying images from one place to other). Manual interaction can cause inconsistencies.
But I assume that for some reason you should do it. So in order to achieve what you want:
DB design
Create a binary column (binary or varbinary) in your table
It is better if you create it in a different table with 1-1 relationship. However the idea is avoiding to load image when hydrating entity. Use a lazy load approach to load your image only when you want.
You have to avoid to load images when you make a big select (for example if you want to load all your entities in a combo avoid SELECT * From whatever) as it will load thousands of images for nothing. As I said this can be done by having images in a different table, or loading only proper columns in SELECT or by making lazy load. (Or even better by NOT having images in DB, only paths)
C# Code
Use BynaryReader to read it
User Byte array to store it
Check this link for code example: http://www.codeproject.com/Articles/21208/Store-or-Save-images-in-SQL-Server
The code is trivial but why the DB?
If this is a website why not save it to a location on disk where you can easily reference it?
Databases are optimised to store data of a known size and relatively small size. Youre image will most likely be more than 8KB in length (mearning its a MAX datatype).
The image will be stored on a separate row/page from your "profile".
Personally I'd save the images in a known folder and use the id for the image name. For profiles that don't have an image and use a standard gif or similar, probably keep it simple / trim by having simlinks/hardlinks of the profile id to the common gif.
public class Profile
{
public int Id {get;}
public string Name {get; private set;}
public Image Picture {get; private set;}
public void Save()
{
using (var connection = new SqlConnection("myconnectionstring"))
using (var command = new SqlCommand("", connection))
{
command.CommandText =
"UPDATE dbo.TblProfile " +
"SET " +
"Name = #name, " +
"Picture = #picture " +
"WHERE ID = #id";
command.Parameters.AddWithValue("#name", Name);
command.Parameters.AddWithValue("#picture", Picture);
command.Parameters.AddWithValue("#id", Id);
command.ExecuteNonQuery();
}
}
}
I think following link would give you the solution,
Upload Image and Save in DB
i'm working on Linq To Sql,WPF and i have a database now i need to save some picture in the database but i don't know which is the correct datatype to save the pictures Database(this database would be connect from 10 users in the same time).
Can you point me in the right way to overcome this step?
If i didn't wrong it is not a good idea to save pictures in the database but if you can advice me a better method i will apply it.
Thanks so much for your time.
Nice Regards
You can use a 'varbinary(MAX)' or 'image' column type. Linq2Sql will auto-generate a class that uses a Binary object to wrap your image. The Binary object is just a wrapper around a byte[].
myObject.Image = new Binary(imageByteArray);
Store your picture as a blob, the variable defined in your class containing the image could be a byte[] stream. Alternatively you just store a reference to the picture in the database and store the image on a file server.
Typically you will use a varbinary(max) -or less than max- on the database side and you will use a byte[] type in your class.
There's a lot of heated debates that occur when people talk about this, I would like to note that you might want to consider storing that path to a network folder in the database.
The disadvantage of storing the actual image in the database is that all those bytes have to get sent back and forth through a sql query and if those images are large you will be increasing the size of your db substantially. along with the weird things that were mentioned above.
Anyways I don't want to open up a can of worms, just wanted to show an alternative.
UPDATE:
Something like this:
public partial class LinqClass
{
public string ImagePath { get; set; }
public System.Drawing.Image Picture
{
get
{
return System.Drawing.Image.FromFile(ImagePath);
}
}
}
where ImagePath is the actual column in the db that you are saving the file path to. This doesn't have the code to save the file (something like File.Save(ImagePath) etc. but it's a start.
I've never done it with Linq, but we used a b64 conversion for the image, then a clob datatype. Then reverse the b64 when you want to view the image.