تصاوير در بانک اطلاعات: از نوع داده IMAGE استفاده نکنيد
از آنجا که مکررا ديده مي شود هنوز دوستان از نوع داده IMAGE استفاده مي کنند، لازم دانستم –با عرض پوزش- اين تذکر را بدهم: مايکروسافت قويا هشدار داده است که ديگر از نوع داده IMAGE استفاده نکنيد و به جاي آن از نوع دادة (VARBINERY(MAX استفاده کنيد؛ بايد بدانيد که نوع دادة IMAGE فقط براي سازگاري با SQL Server 2000 هنوز در SQL Server 2005 وجود دارد و در نگارش بعدي SQL Server ، ديگر اين نوع داده پشتيباني نخواهد شد.
قبل از همه، اين توضيح کوتاه را بدهم که تصوير به صورت آرايه اي از بايتها در بانک اطلاعات ذخيره ميشود. بنا بر اين هنگام نوشتن در بانک يا خواندن از آن، بايد تبديلات لازم صورت گيرد.
اکنون اين پروژه را بامن گام به گام تکميل نماييد:
۱. يک بانک اطلاعات SQL Server به نام PhotoBank ايجاد کنيد که حاوي جدول Persons بافيلدهاي ذيل است.
|
نام فيلد |
توضيح |
|
PersonID (INT Identity) |
کد شخص |
|
FLName |
نام و نام خانوادگي |
|
Pohto |
تصوير |
۲. در ويژوال استوديو يک پروژة Windows Application ايجاد کنيد.
۳. دو GroupBox به فرم بيافزاييد.
۴. در GroupBox اول (سمت چپ) دو Button، يک Lable، يک TextBox و يک PictureBox اضافه کنيد.
۵. در GroupBox دوم يک ListBox و يک PictureBox اضافه کنيد.
۶. اکنون بر روي فرم کليک مضاعف کرده تا ضمن ايجاد متد Load، به ويرايشگر کد منتقل شويد.
اگر فضاي نامهاي ذيل وجود ندارد آنها را وارد کنيد:
VB:
|
Imports System.Data
Imports System.Data.SqlClient
Imports System.IO
|
C#:
|
using System.Data;
using System.Data.SqlClient;
using System.IO;
|
۷. متغيرهاي ذيل را داخل کلاس اعلان کنيد:
VB:
|
Private strSQL As String
Private con As SqlConnection
Private da As SqlDataAdapter
Private com As SqlCommand
Private ds As DataSet
|
C#:
|
private string strSQL;
private SqlConnection con;
private SqlDataAdapter da;
private SqlCommand com;
private DataSet ds; |
۸. اکنون اتصال را در متد Load فرم تنظيم کنيد:
VB:
|
Private Sub frmPhoto_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles MyBase.Load
Try
con = New SqlConnection("Data Source=localhost;Initial " _
& "Catalog=PhotoBank;Integrated Security=True")
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
|
C#:
|
private void frmPhoto_Load(object sender, EventArgs e)
{
try
{
con = new SqlConnection("Data Source=localhost;Initial "
+ "Catalog=PhotoBank;Integrated Security=True");
}
catch (SystemException ex)
{
MessageBox.Show(ex.Message);
}
}
|
۹. متد دکمة اول را (که براي انتخاب تصوير است) اين گونه بنويسيد:
VB:
|
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnChoose.Click
Try
Dim dlgOpen As New OpenFileDialog
With dlgOpen
.Filter = "Image Files(*.BMP;*.JPG;*.GIF)|*.BMP;*.JPG;*.GIF"
.Title = "انتخاب تصوير"
If .ShowDialog = Windows.Forms.DialogResult.OK Then
Me.PictureBox1.Image = Image.FromFile(.FileName)
End If
End With
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
|
C#:
|
private void button1_Click(object sender, EventArgs e)
{
try
{
OpenFileDialog dlgOpen = new OpenFileDialog();
dlgOpen.Filter =
"Image Files(*.BMP;*.JPG;*.GIF)|*.BMP;*.JPG;*.GIF";
dlgOpen.Title = "انتخاب تصوير";
if (dlgOpen.ShowDialog() == DialogResult.OK)
pictureBox1.Image = Image.FromFile(dlgOpen.FileName);
}
catch (SystemException ex)
{
MessageBox.Show(ex.Message);
}
}
|
۱۰. و متد دکمة دوم براي درج و ذخيرة تصوير و نام نام خانوادگيِ شخص را اين گونه بنويسيد:
VB:
|
Private Sub Button2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click
Try
strSQL = "INSERT INTO Persons (FLName, Photo) VALUES (@FLName, @Photo)"
Dim ms As New MemoryStream
Me.PictureBox1.Image.Save(ms, Me.PictureBox1.Image.RawFormat)
Dim arrPic() As Byte = ms.GetBuffer
ms.Close()
con.Open()
com = New SqlCommand(strSQL, con)
com.Parameters.Add("@FLName", SqlDbType.NVarChar, 50).Value = Me.TextBox1.Text
com.Parameters.Add("@Photo", SqlDbType.VarBinary).Value = arrPic
com.ExecuteNonQuery()
con.Close()
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
|
C#:
|
private void button2_Click(object sender, EventArgs e)
{
try
{
strSQL = "INSERT INTO Persons (FLName, Photo) VALUES (@FLName, @Photo)";
MemoryStream ms = new MemoryStream();
pictureBox1.Image.Save(ms, pictureBox1.Image.RawFormat);
byte[] arrPic = ms.GetBuffer();
ms.Close();
con.Open();
com = new SqlCommand(strSQL, con);
com.Parameters.Add("@FLName", SqlDbType.NVarChar, 50).Value = textBox1.Text;
com.Parameters.Add("@Photo", SqlDbType.VarBinary).Value = arrPic;
com.ExecuteNonQuery();
con.Close();
}
catch (SystemException ex)
{
MessageBox.Show(ex.Message);
}
}
|
فکر مي کنم فقط اين متد است که کمي نياز به توضيح دارد: همان گونه که گفته شد، تصاوير به صورت آرايه و جرياني از بايت ها در بانک اطلات ذخيره مي شود. بنا بر اين ابتدا يک MemomryStream ايجاد مي کنيم؛ سپس با استفاده از متد Save، تصوير PictureBox1 را در آن ذخيره مي کنيم؛ آنگاه يک آرايه از نوع بايت اعلان کرده و آن را با استفاده از همان MemomryStream مقداردهي مي کنيم. بقيه کد کاملا واضح است (فرض مي کنم که شما با برنامه نويسي بانک اطلاعات آشنايي داريد).
اکنون ميتوانيد پروژه را امتحان کرده و در جعبه متن نام و نام خانوادگي شخص را نوشته، تصوير دلخواه را انتخاب کرده و دکمة ذخيره را کليک کنيد تا دادهها در بانک اطلاعات ذخيره شود.
۱۱. يک متد هم براي پر کردن ليست (در GroupBox دوم) لازم داريم:
VB:
|
Private Sub PapulateListBox()
Try
strSQL = "SELECT * FROM Persons"
da = New SqlDataAdapter(strSQL, con)
ds = New DataSet
con.Open()
da.Fill(ds, "Persons")
con.Close()
Me.ListBox1.DataSource = ds.Tables("Persons")
Me.ListBox1.DisplayMember = "FLName"
Me.ListBox1.ValueMember = "PersonID"
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
|
C#:
|
private void papulateListBox()
{
try
{
strSQL = "SELECT * FROM Persons";
da = new SqlDataAdapter(strSQL, con);
ds = new DataSet();
con.Open();
da.Fill(ds, "Persons");
con.Close();
listBox1.DataSource = ds.Tables["Persons"];
listBox1.DisplayMember = "FLName";
listBox1.ValueMember = " PersonID";
}
catch (SystemException ex)
{
MessageBox.Show(ex.Message);
}
}
|
نام اين متد را در متدِ Load فرم کپي کنيد تا هنگام بارگزاري صفحه، اين ليست پر شود.
۱۲. هر گاه کاربر يکي از آيتمهاي اين ليست را کليک ميکند، بايد تصوير مربوط به آن شخص در PictureBox دوم نشان داده شود (خواندن از بانک اطلاعات)؛ بنا بر اين متد ذيل را بنويسيد:
VB:
|
Private Sub ListBox1_Click(ByVal sender As Object, ByVal e As _
System.EventArgs) Handles ListBox1.Click
Try
strSQL = "SELECT * FROM Persons WHERE PersonID = @PersonID"
da = New SqlDataAdapter(strSQL, con)
da.SelectCommand.Parameters.Add("@PersonID", SqlDbType.Int).Value = _
CInt(Me.ListBox1.SelectedValue)
ds = New DataSet
con.Open()
da.Fill(ds, "Persons")
con.Close()
Dim arrPic() As Byte = CType(ds.Tables("Persons") _
.Rows(0).Item("Photo"), Byte())
Dim ms As New MemoryStream(arrPic)
Me.PictureBox2.Image = Image.FromStream(ms)
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
|
C#:
|
private void listBox1_Click(object sender, EventArgs e)
{
try
{
strSQL = "SELECT * FROM Persons WHERE PersonID = @PersonID";
da = new SqlDataAdapter(strSQL, con);
da.SelectCommand.Parameters.Add("@PersonID",
SqlDbType.Int).Value = listBox1.SelectedValue;
ds = new DataSet();
con.Open();
da.Fill(ds, "Persons");
con.Close();
byte[] arrPic = (byte[])(ds.Tables["Persons"].Rows[0]["Photo"]);
MemoryStream ms = new MemoryStream(arrPic);
pictureBox2.Image = Image.FromStream(ms);
}
catch (SystemException ex)
{
MessageBox.Show(ex.Message);
}
}
|
اکنون ميتوانيد برنامه را به طور کامل امتحان کنيد:
در پايان اين مقاله بد نيست به نحوة انقياد کنترل ها به يک فيلد تصويري اشاره اي داشته باشم:
اگر شما از کنترلهاي مقيد به داده (کنترل هايي که به صورت دوطرفه مقيد هستند)، استفاده ميکنيد، خود ويژوال استوديو تبديلات لازم را انجام ميدهد. در غير اين صورت، شما بايد اين کار را انجام دهيد.
نحوة انقيادِ يک PictureBox با استفاده از يک فيلد جدول همانند ذيل است:
VB:
|
Me.PhotoPictureBox.DataBindings.Add(New _
System.Windows.Forms.Binding("Image", ds, "Customers.Photo", True))
|
C#:
|
this.photoPictureBox.DataBindings.Add(new
System.Windows.Forms.Binding("Image", ds, " Customers.Photo", true));
|
و نحوة انقياد با استفاده از يک کنترل BindingSource همانند ذيل ميتواند باشد:
VB:
|
Me.PhotoPictureBox.DataBindings.Add(New _
System.Windows.Forms.Binding("Image", Me.CustomersBindingSource, "Photo", True))
|
C#:
|
this.photoPictureBox.DataBindings.Add(new
System.Windows.Forms.Binding("Image", this.customersBindingSource, "Photo", true));
|