02-12-15, 08:42 PM
السلام عليكم ورحمة الله وبركاته
مقدمــــة:
الهدف من الموضوع هو بناء Collection تدعم الداتا بيز
في الجزء الأول Collection & DataBase Part 1 تم توضيح كيفية بناء Collection من الصفر لكن وبما أن الدوت نت به الكثير من Collection وبها صفات أفضل كثيرا مما كتبناه سابقا في الجزء الأول لذلك ومن الأفضل أن نستخدم بعضا من Collections المتاحة لنا في الدوت نت و بالتالي هذا سيوفر علينا الكثير من الجهد والوقت
في أي برامج داتا بيز نحتاج الي تخزين بيانات بأشكال مختلفة علي سبيل المثال نحتاج الي تخزين بيانات اسعار او معاملات تجارية او بيانات شخصية او بيانات عامة او بيانات خاصة بالشركات و المؤسسات و الأفراد عموما مهما كان شكل المدخلات التي نريد الاحتفاظ بها و تخزينها فإن الاسلوب المستخدم سيظل واحدا مهما اختلفت التقنية المستخدمة في تخزين البيانات
وبدلا من الجديث النظري ولتوضيح الأمر قليلا سنعطي مثالا توضيحيا
مثال:
لنفترض ان هناك شركة ما تريد تخزين بيانات الموظفين و العاملين بها وهه البيانات عبارة عن إسم الموظف - الراتب الشهري - تاريخ الإلتحاق بالشركة - صورة شخصية للموظف و أشياء أخري من هذه الأمور
لذلك نحن نحتاج الي كلاس سيكون الهدف منه إدخال البياات الي الداتا بيز و هذا الكلاس سوف نطلق عليه الإسم Person
وبما ان الشركة ليس بها موظفا واحدا وربما عدد موظفيها قد يتعدي المئات أو الالاف من الأشخاص لذلك نحن هنا نحتاج إلي Collection نخزن بها البيانات الخاصة بكل شخص اأو نخزن بها المدخلات و لسوف نطلق علي هذه Collection الإسم PersonCollection
الكلاس Person
هذا الكلاس مثله مثل اي كلاس سيكون له Constructor و سيكون به بعض Property تعبر عن المدخلات الخاصة بكل شخص لكن يتبقي بعض الاسئلة الهامة جدا وهي كالتالي و يجب ان نضع في الاعتبار ان الاجابة علي هذه الاسئلة سيؤثر علي شكل الكود الخاص بالكلاس :
1- هل نريد الاحتفاظ بصورة لكل موظف؟ إن كانت الإجابة نعم إذن هذا الكلاس يجب أن يدعم IDisposable Interface
2- كيف يتم التفريق بين المدخلات الخاصة بكل بالموظفين ؟ في الداتا بيز التقليدية مثل SQL سنجد ان أي ملف نقوم ببنائه يكون به مفتاح خاص وهذا المفتاح يتم استخدامه لإعطاء رقم متفرد لكل موظف وغالبا هذا المفتاح الهدف منه هو تسهيل عمليات البحث و الفلترة للموظفين
وبشكل مبدئي الكلاس Person سيكون به مدخلات بسيطة مثل إسم الشخص و المفتاح الخاص بهذا الشخص و رقم التليفون و صورة لهذا الشخص و لاحقا وكلما تقدمنا في الموضوعات التي تناقش نفس فكرة المقال سوف نضيف للكلاس بيانات اخري.
و هنا لننظر للأمر قليلا و نتساءل هل يجب ان يقوم المستخدم بإدخال رقم يتم استخدامه بمثابة مفتاح لكل شخص ام يجب علينا أن نضيف هذا المفتاح بشكل اتوماتيكي بحيث يكون له ارتباط باسم الشخص
الخياران متاحان و الأمر بالنهاية متروك للمبرمج
عموما الفكرة المستخدمة في كيفية صناعة مفتاح متفرد لكل شخص يتم إدخال بياناته يمكن تطويرها و استخدامها لتوليد SerialNo لحماية البرنامج.
الدوال التالية توضح كيفية توليد رقم يمكن استخدامه كنوع من المفتاح للتعريف عن كل شخص
و علي فكرة انا لم أخترع شيئاجديدا فقط أنا قرأت الأمثلة الموجودة في مواقع مايكروسوفت و اخذت منها و قمت ببناء الدوال بما يتناسب مع احتياجات الموضوع الذي نتحدث عنه و الدول يمكن كتابتها في كلاس منفصل او يمكن اضافتها للكلاس Person و الأمر متروك للمبرمج
يجب إضافة فضاء الاسماء System.Numerics لكي تعمل الدول بدو أخطاء
عموما الدالتان أعلاه تؤديان نفس الغرض و عليك فقط ان تستخدم احدهما
أيضا وفي المرفقات ستجدون مثالا لكيفية استخدام هذا الدوال في توليد ارقام يمكن استخادمها لحماية برامجنا
كودالكلاس Person
كيف نستخدم الأكواد أعلاه مع الفورم و الكونترول الموجودة علي الفورم وذلك بدون بناء Collection من الصفر
اولا : داخل الفورم نقوم بتعريف متغير يعبر عن اي Collection أو Generic List الموجودة بكثرة في الدوت نت و هنا سوف استخدم Generic List
لكن قبل ان نفعل اي شئ بالكود نحن هنا نحتاج الي ايجاد شخص ما داخل Generic List لذلك نحن نحتاج الي أن نكتب بعض الدوال التي سوف تساعدنا علي ايجاد أي شخص موجود في Generic List
الدوال التالية توضح كيف نقوم بإيجاد شخص ما باستخدام LINQ و الكود يوضح ايضا طريقة اخري لكي نفعل هذا
ثانيا: نقوم بإضافة بعض الاشخاص الي Generic List و ذلك في الحدث Load الخاص ب الفورم
ثالثا: نعرض البيانات في اي كونترول مثل ListBox
الان كيف نربط البيانات مع الداتا جريد فيو
يمكننا ان نستخدم اي اسلوب نراه مناسباأو من الأفضل و الاسهل لنا هو أن نقوم بتحويل البيانات الموجودة في Generic List الي Data Table لتكون بمثابة Data Source للداتا جريد فيو
كيف نقوم بتحويل Generic List التي تم تعريفها اعلاه في الكود الي Data table
الكود التالي يوضح كيف نفعل ذلك
طبعا و بدلا من ان نكتب كل هذه الأكواد في الفورم من الأسهل لنا أن تبني Collection خاصة و هذا سوف يقوم بتسهيل عمليات الحذف و البحث و خلافة وهذا ما سنوضحه في الجزء الثالث إن شاء الله
قد يتساءل البعض أليس من الأسهل استخدام LINQ to SQL or LINQ to XML
بالطبع نعم أسهل ويمكن عمل ذلك بكل بساطة
لكن بعض الفئات من المبرمجين يفضلون بناء كل شئ ب أنفسهم و مايكروسوفت تركت جميع الخيارت متاحة طبقا لرؤية كل مبرمج
في المرفقات ستجدون جميع الاكواد اعلاه بنسخة الفيجوال استوديو 2012
مع تحياتي بالتوفيق للجميع
مقدمــــة:
الهدف من الموضوع هو بناء Collection تدعم الداتا بيز
في الجزء الأول Collection & DataBase Part 1 تم توضيح كيفية بناء Collection من الصفر لكن وبما أن الدوت نت به الكثير من Collection وبها صفات أفضل كثيرا مما كتبناه سابقا في الجزء الأول لذلك ومن الأفضل أن نستخدم بعضا من Collections المتاحة لنا في الدوت نت و بالتالي هذا سيوفر علينا الكثير من الجهد والوقت
في أي برامج داتا بيز نحتاج الي تخزين بيانات بأشكال مختلفة علي سبيل المثال نحتاج الي تخزين بيانات اسعار او معاملات تجارية او بيانات شخصية او بيانات عامة او بيانات خاصة بالشركات و المؤسسات و الأفراد عموما مهما كان شكل المدخلات التي نريد الاحتفاظ بها و تخزينها فإن الاسلوب المستخدم سيظل واحدا مهما اختلفت التقنية المستخدمة في تخزين البيانات
وبدلا من الجديث النظري ولتوضيح الأمر قليلا سنعطي مثالا توضيحيا
مثال:
لنفترض ان هناك شركة ما تريد تخزين بيانات الموظفين و العاملين بها وهه البيانات عبارة عن إسم الموظف - الراتب الشهري - تاريخ الإلتحاق بالشركة - صورة شخصية للموظف و أشياء أخري من هذه الأمور
لذلك نحن نحتاج الي كلاس سيكون الهدف منه إدخال البياات الي الداتا بيز و هذا الكلاس سوف نطلق عليه الإسم Person
وبما ان الشركة ليس بها موظفا واحدا وربما عدد موظفيها قد يتعدي المئات أو الالاف من الأشخاص لذلك نحن هنا نحتاج إلي Collection نخزن بها البيانات الخاصة بكل شخص اأو نخزن بها المدخلات و لسوف نطلق علي هذه Collection الإسم PersonCollection
الكلاس Person
هذا الكلاس مثله مثل اي كلاس سيكون له Constructor و سيكون به بعض Property تعبر عن المدخلات الخاصة بكل شخص لكن يتبقي بعض الاسئلة الهامة جدا وهي كالتالي و يجب ان نضع في الاعتبار ان الاجابة علي هذه الاسئلة سيؤثر علي شكل الكود الخاص بالكلاس :
1- هل نريد الاحتفاظ بصورة لكل موظف؟ إن كانت الإجابة نعم إذن هذا الكلاس يجب أن يدعم IDisposable Interface
2- كيف يتم التفريق بين المدخلات الخاصة بكل بالموظفين ؟ في الداتا بيز التقليدية مثل SQL سنجد ان أي ملف نقوم ببنائه يكون به مفتاح خاص وهذا المفتاح يتم استخدامه لإعطاء رقم متفرد لكل موظف وغالبا هذا المفتاح الهدف منه هو تسهيل عمليات البحث و الفلترة للموظفين
وبشكل مبدئي الكلاس Person سيكون به مدخلات بسيطة مثل إسم الشخص و المفتاح الخاص بهذا الشخص و رقم التليفون و صورة لهذا الشخص و لاحقا وكلما تقدمنا في الموضوعات التي تناقش نفس فكرة المقال سوف نضيف للكلاس بيانات اخري.
و هنا لننظر للأمر قليلا و نتساءل هل يجب ان يقوم المستخدم بإدخال رقم يتم استخدامه بمثابة مفتاح لكل شخص ام يجب علينا أن نضيف هذا المفتاح بشكل اتوماتيكي بحيث يكون له ارتباط باسم الشخص
الخياران متاحان و الأمر بالنهاية متروك للمبرمج
عموما الفكرة المستخدمة في كيفية صناعة مفتاح متفرد لكل شخص يتم إدخال بياناته يمكن تطويرها و استخدامها لتوليد SerialNo لحماية البرنامج.
الدوال التالية توضح كيفية توليد رقم يمكن استخدامه كنوع من المفتاح للتعريف عن كل شخص
و علي فكرة انا لم أخترع شيئاجديدا فقط أنا قرأت الأمثلة الموجودة في مواقع مايكروسوفت و اخذت منها و قمت ببناء الدوال بما يتناسب مع احتياجات الموضوع الذي نتحدث عنه و الدول يمكن كتابتها في كلاس منفصل او يمكن اضافتها للكلاس Person و الأمر متروك للمبرمج
يجب إضافة فضاء الاسماء System.Numerics لكي تعمل الدول بدو أخطاء
PHP كود :
Friend Function GenerateKeyLINQ(value As String) As String
Dim textValue As String = value
Dim keyValue As String = CType(Nothing, String)
If Not String.IsNullOrEmpty(textValue) Then
Dim query As IEnumerable(Of Char) = From c As Char In textValue Where (Not Char.IsWhiteSpace(c) AndAlso Char.IsLetter(c)) Select c
Dim number As BigInteger = 1
For Each c As Char In query
Dim i As BigInteger = New BigInteger((Encoding.ASCII.GetBytes(c.ToString)))
number *= i
Next
number *= value.Length
' if longer number required uncomment the below line of code
'number = Math.Pow(number, 2)
number = BigInteger.Abs(number)
Dim bytes As List(Of Byte) = New List(Of Byte)
For Each c As Char In number.ToString
bytes.Add(Convert.ToByte(c))
Next
Dim nString As String = Convert.ToBase64String(bytes.ToArray)
nString = nString.Replace("=", "")
nString = nString.Replace("+", "")
keyValue = number.ToString & " - " & nString.ToUpper
End If
Return keyValue
End Function
Friend Function GenerateKey(value As String) As String
Dim textValue As String = value
Dim keyValue As String = CType(Nothing, String)
If Not String.IsNullOrEmpty(textValue) Then
Dim number As BigInteger = 1
For i As Integer = 0 To textValue.Length - 1
Dim c As Char = textValue(i)
If Not Char.IsWhiteSpace(c) AndAlso Char.IsLetter(c) Then
Dim j As BigInteger = New BigInteger((Encoding.ASCII.GetBytes(c.ToString)))
number *= j
End If
Next
number *= value.Length
' if longer number required uncomment the below line of code
'number = Math.Pow(number, 2)
number = BigInteger.Abs(number)
Dim bytes As List(Of Byte) = New List(Of Byte)
For Each c As Char In number.ToString
bytes.Add(Convert.ToByte(c))
Next
Dim nString As String = Convert.ToBase64String(bytes.ToArray)
nString = nString.Replace("=", "")
nString = nString.Replace("+", "")
keyValue = number.ToString & " - " & nString.ToUpper
End If
Return keyValue
End Function
عموما الدالتان أعلاه تؤديان نفس الغرض و عليك فقط ان تستخدم احدهما
أيضا وفي المرفقات ستجدون مثالا لكيفية استخدام هذا الدوال في توليد ارقام يمكن استخادمها لحماية برامجنا
كودالكلاس Person
PHP كود :
Imports System.Numerics
Imports System.Text
Public Class Person
Implements IDisposable
Private _key As String = CType(Nothing, String)
Private _img As Image = CType(Nothing, Image)
Private _disposed As Boolean
Public Sub New(name As String, img As Image, cellNo As String)
If String.IsNullOrEmpty(name) Then
Throw New ArgumentException("Please specify the person name", "name")
End If
Me.Name = name
Me._key = Me.GenerateKeyLINQ(Me.Name)
Me.Image = img
Me.CellNo = cellNo
End Sub
Public Property Name As String
Public Property CellNo As String
Public Property Image As Image
Get
Return Me._img
End Get
Set(value As Image)
If Me._img IsNot value Then
Me._img = value
End If
End Set
End Property
Protected ReadOnly Property Key As String
Get
Return Me._key
End Get
End Property
' for Test purpose only
Friend ReadOnly Property ID As String
Get
Return Me._key
End Get
End Property
Friend Function GenerateKeyLINQ(value As String) As String
Dim textValue As String = value
Dim keyValue As String = CType(Nothing, String)
If Not String.IsNullOrEmpty(textValue) Then
Dim query As IEnumerable(Of Char) = From c As Char In textValue Where (Not Char.IsWhiteSpace(c) AndAlso Char.IsLetter(c)) Select c
Dim number As BigInteger = 1
For Each c As Char In query
Dim i As BigInteger = New BigInteger((Encoding.ASCII.GetBytes(c.ToString)))
number *= i
Next
number *= value.Length
' if longer number required uncomment the below line of code
'number = Math.Pow(number, 2)
number = BigInteger.Abs(number)
Dim bytes As List(Of Byte) = New List(Of Byte)
For Each c As Char In number.ToString
bytes.Add(Convert.ToByte(c))
Next
Dim nString As String = Convert.ToBase64String(bytes.ToArray)
nString = nString.Replace("=", "")
nString = nString.Replace("+", "")
keyValue = number.ToString & " - " & nString.ToUpper
End If
Return keyValue
End Function
Protected Sub OnDispose()
If Me._img IsNot Nothing Then
Me._img.Dispose()
Me._img = Nothing
End If
End Sub
Protected Overridable Sub Dispose(disposing As Boolean)
If Me._disposed Then
Return
End If
If disposing Then
Me.OnDispose()
End If
Me._disposed = True
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
End Class
كيف نستخدم الأكواد أعلاه مع الفورم و الكونترول الموجودة علي الفورم وذلك بدون بناء Collection من الصفر
اولا : داخل الفورم نقوم بتعريف متغير يعبر عن اي Collection أو Generic List الموجودة بكثرة في الدوت نت و هنا سوف استخدم Generic List
PHP كود :
Private persons As New List(Of Person)
لكن قبل ان نفعل اي شئ بالكود نحن هنا نحتاج الي ايجاد شخص ما داخل Generic List لذلك نحن نحتاج الي أن نكتب بعض الدوال التي سوف تساعدنا علي ايجاد أي شخص موجود في Generic List
الدوال التالية توضح كيف نقوم بإيجاد شخص ما باستخدام LINQ و الكود يوضح ايضا طريقة اخري لكي نفعل هذا
PHP كود :
' You may use LINQ to find the person by his name
Friend Function FindPerson(name As String) As Person
Dim result As Person = CType(Nothing, Person)
If Not (String.IsNullOrEmpty(name)) Then
For Each p As Person In Me.persons
If p.Name.ToLowerInvariant() = name.ToLowerInvariant() Then
result = p
Exit For
End If
Next
End If
Return result
End Function
Friend Function FindPersonLINQ(name As String) As Person
Dim result As Person = CType(Nothing, Person)
Dim query As IEnumerable(Of Person) = CType(Nothing, IEnumerable(Of Person))
If Not (String.IsNullOrEmpty(name)) Then
query = From anyPerson As Person In persons Where anyPerson.Name.ToLowerInvariant() = name.ToLowerInvariant() Select anyPerson
End If
For Each item As Person In query
result = New Person(item.Name, item.Image, item.CellNo)
Next
Return result
End Function
Friend Function FindPersonKey(name As String) As String
Return FindPerson(name).ID
End Function
Friend Function FindStudentPhone(name As String) As String
Return FindPerson(name).CellNo
End Function
ثانيا: نقوم بإضافة بعض الاشخاص الي Generic List و ذلك في الحدث Load الخاص ب الفورم
PHP كود :
Dim p1 As Person = New Person("Ahmed Reda", Nothing, "01099999999")
Dim p2 As Person = New Person("Ahmed ali", Nothing, "01088888888")
Dim p3 As Person = New Person("Ahmed Mahmoud", Nothing, "01077777777")
Dim p4 As Person = New Person("Ahmed Alaa", Nothing, "01066666666")
Dim p5 As Person = New Person("Ahmed Mostafa", Nothing, "01055555555")
Dim p6 As Person = New Person("Ahmed Omar", Nothing, "01044444444")
ثالثا: نعرض البيانات في اي كونترول مثل ListBox
PHP كود :
For Each p As Person In persons
ListBox1.Items.Add(p.Name)
Next
الان كيف نربط البيانات مع الداتا جريد فيو
يمكننا ان نستخدم اي اسلوب نراه مناسباأو من الأفضل و الاسهل لنا هو أن نقوم بتحويل البيانات الموجودة في Generic List الي Data Table لتكون بمثابة Data Source للداتا جريد فيو
كيف نقوم بتحويل Generic List التي تم تعريفها اعلاه في الكود الي Data table
الكود التالي يوضح كيف نفعل ذلك
PHP كود :
Friend Function PersonsToDataTable() As DataTable
Dim result As DataTable = CType(Nothing, DataTable)
result = New DataTable With {.Locale = System.Globalization.CultureInfo.InvariantCulture}
result.Columns.Add(New DataColumn("Key", GetType(String)))
result.Columns.Add(New DataColumn("Name", GetType(String)))
result.Columns.Add(New DataColumn("Phone", GetType(String)))
result.Columns.Add(New DataColumn("Image", GetType(Image)))
SyncLock Me.persons.GetType
For i As Integer = 0 To Me.persons.Count - 1
result.Rows.Add(New Object() {Me.persons(i).ID, Me.persons(i).Name, Me.persons(i).CellNo, Me.persons(i).Image})
Next
Return result
End SyncLock
End Function
طبعا و بدلا من ان نكتب كل هذه الأكواد في الفورم من الأسهل لنا أن تبني Collection خاصة و هذا سوف يقوم بتسهيل عمليات الحذف و البحث و خلافة وهذا ما سنوضحه في الجزء الثالث إن شاء الله
قد يتساءل البعض أليس من الأسهل استخدام LINQ to SQL or LINQ to XML
بالطبع نعم أسهل ويمكن عمل ذلك بكل بساطة
لكن بعض الفئات من المبرمجين يفضلون بناء كل شئ ب أنفسهم و مايكروسوفت تركت جميع الخيارت متاحة طبقا لرؤية كل مبرمج
في المرفقات ستجدون جميع الاكواد اعلاه بنسخة الفيجوال استوديو 2012
مع تحياتي بالتوفيق للجميع