بسم الله الرحمن الرحيم
نكمل ما بدأناه سابقا
سنحاول ان نفصل اكواد الاتصال و الحفظ في كلاس منفصل
سيكون لدي Module اسمه Connect
و نبدء باستيراد مجالات الاسماء و تعريف المتغيرات اللازمة لاجراء عملية الاتصال و كذلك الكائنات اللازمة لنقل البيانات و حفظها من و الى القاعدة
في اعلى Module المسمى Connect
استوردنا المجالات اللازمة للتعامل مع قاعدة البيانات من النوع Access
الان داخل Module نعرف الكائنات التالية
- السطر الاول هو مسار قاعدة البيانات داخل البرنامج و اسمها Coder
- السطر الثاني كائن اتصال ليؤمن لنا عملية فتح و اغلاق الاتصال مع قاعدة البيانات
- السطر الثالث مجموعة من كائنات DataAdapter سوف نستخدمها لنقل البيانات من و الى القاعدة كل واحد منها لجدول و يتضح ذلك عبر اسمائها
- السطر الرابع مجموعة من كائنات CommanBuilder سنستخدمها لتقوم بعمليات توليد جمل الادخال و التعديل و الحذف لكل جدول بدل من كتابة و تكرار جمل
الادخال , هذا الكائن سحري في التعامل مع قواعد البيانات .
- السطر الخامس حاوية البيانات (قاعدة بيانات مؤقتة) سنستخدمها لنضيف اليها الجداول السابقة.
- السطر السادس حاوية بيانات اخرى فقط لجدول LOgins السابق ذكره.
ساقوم بعدها بانشاء بعض Functions التي تسهل علينا العمل
كما تلاحظ دالة بسيطة تعيد لي جدول بيانات الانواع , تحتوي على جملة تحديد مجموعة سجلات من الجدول
ثم يقوم ناقل البيانات KindDa وفق الاتصال الممنوح له بجلب البيانات ووضعها في جدول في حاوية البيانات
لاحظ اننا فرضنا شروطا على هذا الناقل بان يقوم يقوم بتوريث مخطط الجدول الى حاوية البيانات و كذلك
فرض مفتاح اساسي في حال وجد في بنية الجدول المنقول.
اذ ستحتوي حاوية البيانات Mydataset على نفس اسم الجدول و كذلك على نفس اسماء الاعمدة في الجدول الاصل
بنفس التخطيط هذا السطر هو المسؤول عن العملية
اما السطر الاخر فهو سيفرض مفتاح رئيسي في الجدول على على الحقل ذو القيد PrimaryKey و هو هنا Id
سنكرر العملية لكل جدول نريد التعامل معه كما يلي
جدول الاكواد
جدول المواضيع او المقالات
جدول الفروع
جدول المرفقات
جدول المواقع
بعد ذلك سنقوم بعمل اجراء خاص لفرض العلاقات بين الجداول و نقوم باضافته الى حاوية البيانات MyDataset
تابع الكود التالي
الكود بسط جدا ان شاء الله و ساشرحه هنا
بعد ذلك سنقوم بعمل دالة Function تعيد لنا كائن Dataset معبئ بالجداول و العلاقات كما نحب و نشتهي
اضن الكود سهل الهضم و لا يحتاج شرح فهو تجميع للدوال السابقة.
الان ناتي الى اجراء الحفظ الخاص بكل ما جرى على الجداول من حذف و اضافة و تعديل
السيناريو الذي ستعمل معه هو تفحص تغير سجلات القاعدة المؤقته (MyDataset)
و نؤخذ نسخة من كل السجلات التي تعرضت للاضافة او التعديل او الحذف و نرحلها الى قاعدة مؤقته جديدة ساسميها SaveDataset
تحتوي فقط على السجلات المحدثة(مضاف-معدل-محذوف)
ثم سنقوم بارسال التحديثات الى القاعدة الاصل (Access Database)
و بعد الحصول على التحديثات من القاعدة سنقوم بدمج Mydataset مع SaveDataset
وقبول التغيرات الحاصلة .
طريقة سهلة و واضحة و قوية و هي لب الاتصال المنفصل
لنرى ذلك عبر الكود اللذيذ مع الشرح
الشرح
و كذلك اجراء الحفظ الخاص به و هو كسابقه الخاص بحفظ التغيرات على الجداول السابقة
نفس شرح الكود السابق ؟؟
هكذا نكون قد انتهينا من كلاس الاتصال و الحفظ الخاص بنا
يتبع......
نكمل ما بدأناه سابقا
سنحاول ان نفصل اكواد الاتصال و الحفظ في كلاس منفصل
سيكون لدي Module اسمه Connect
و نبدء باستيراد مجالات الاسماء و تعريف المتغيرات اللازمة لاجراء عملية الاتصال و كذلك الكائنات اللازمة لنقل البيانات و حفظها من و الى القاعدة
في اعلى Module المسمى Connect
كود :
Imports System.Data
Imports System.Data.OleDbاستوردنا المجالات اللازمة للتعامل مع قاعدة البيانات من النوع Access
الان داخل Module نعرف الكائنات التالية
كود :
Module Connect
Public ConnectionString As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\Coder.accdb"
Public Con As New OleDbConnection(ConnectionString)
Dim KindDa, CodeDa, InfoDa, PostDa, AttachDa, LoginDa As New OleDb.OleDbDataAdapter
Dim ComBulder1, ComBulder2, ComBulder3, ComBulder4, ComBulder5, ComBulder6 As New OleDbCommandBuilder
Public MyDataset As New DataSet
Private LoginDataSet As New DataSet- السطر الثاني كائن اتصال ليؤمن لنا عملية فتح و اغلاق الاتصال مع قاعدة البيانات
- السطر الثالث مجموعة من كائنات DataAdapter سوف نستخدمها لنقل البيانات من و الى القاعدة كل واحد منها لجدول و يتضح ذلك عبر اسمائها
- السطر الرابع مجموعة من كائنات CommanBuilder سنستخدمها لتقوم بعمليات توليد جمل الادخال و التعديل و الحذف لكل جدول بدل من كتابة و تكرار جمل
الادخال , هذا الكائن سحري في التعامل مع قواعد البيانات .
- السطر الخامس حاوية البيانات (قاعدة بيانات مؤقتة) سنستخدمها لنضيف اليها الجداول السابقة.
- السطر السادس حاوية بيانات اخرى فقط لجدول LOgins السابق ذكره.
ساقوم بعدها بانشاء بعض Functions التي تسهل علينا العمل
كود :
'جدول الانواع
Private Function LoadKindTable() As DataTable
Dim SelectField As String = "Select Id,Kind,Not1 From Kind"
KindDa = New OleDbDataAdapter(SelectField, ConnectionString)
KindDa.MissingSchemaAction = MissingSchemaAction.AddWithKey
KindDa.MissingMappingAction = MissingMappingAction.Passthrough
KindDa.Fill(MyDataset, "kind")
Return MyDataset.Tables("Kind")
End Functionكما تلاحظ دالة بسيطة تعيد لي جدول بيانات الانواع , تحتوي على جملة تحديد مجموعة سجلات من الجدول
ثم يقوم ناقل البيانات KindDa وفق الاتصال الممنوح له بجلب البيانات ووضعها في جدول في حاوية البيانات
لاحظ اننا فرضنا شروطا على هذا الناقل بان يقوم يقوم بتوريث مخطط الجدول الى حاوية البيانات و كذلك
فرض مفتاح اساسي في حال وجد في بنية الجدول المنقول.
اذ ستحتوي حاوية البيانات Mydataset على نفس اسم الجدول و كذلك على نفس اسماء الاعمدة في الجدول الاصل
بنفس التخطيط هذا السطر هو المسؤول عن العملية
كود :
KindDa.MissingMappingAction = MissingMappingAction.Passthroughاما السطر الاخر فهو سيفرض مفتاح رئيسي في الجدول على على الحقل ذو القيد PrimaryKey و هو هنا Id
كود :
KindDa.MissingSchemaAction = MissingSchemaAction.AddWithKeyسنكرر العملية لكل جدول نريد التعامل معه كما يلي
جدول الاكواد
كود :
'جدول الاكواد
Private Function LoadCodeTable() As DataTable
Dim SelectField As String = "Select Id2,Not1,Not2,Code1,Code2,Kind_id From coder"
CodeDa = New OleDbDataAdapter(SelectField, ConnectionString)
CodeDa.MissingSchemaAction = MissingSchemaAction.AddWithKey
CodeDa.MissingMappingAction = MissingMappingAction.Passthrough
CodeDa.Fill(MyDataset, "Coder")
Return MyDataset.Tables("Coder")
End Functionجدول المواضيع او المقالات
كود :
'جدول المقالات
Private Function LoadInfoTable() As DataTable
Dim SelectField As String = "Select IdInfo,Infoname,Content,UrlInfo,Id_Kind From Info"
InfoDa = New OleDbDataAdapter(SelectField, ConnectionString)
InfoDa.MissingSchemaAction = MissingSchemaAction.AddWithKey
InfoDa.MissingMappingAction = MissingMappingAction.Passthrough
InfoDa.Fill(MyDataset, "Info")
Return MyDataset.Tables("Info")
End Functionجدول الفروع
كود :
'جدول الفروع
Private Function LoadposterTable() As DataTable
Dim SelectField As String = "Select id_post,poname,id_k From poster"
PostDa = New OleDbDataAdapter(SelectField, ConnectionString)
PostDa.MissingSchemaAction = MissingSchemaAction.AddWithKey
PostDa.MissingMappingAction = MissingMappingAction.Passthrough
PostDa.Fill(MyDataset, "post")
Return MyDataset.Tables("post")
End Functionجدول المرفقات
كود :
'جدول المرفقات
Private Function LoadAttachTable() As DataTable
Dim SelectField As String = "Select Attach_Id,AttachName,AttachPath,Id_inf From Attaches "
AttachDa = New OleDbDataAdapter(SelectField, ConnectionString)
AttachDa.MissingSchemaAction = MissingSchemaAction.AddWithKey
AttachDa.MissingMappingAction = MissingMappingAction.Passthrough
AttachDa.Fill(MyDataset, "Attach")
Return MyDataset.Tables("Attach")
End Functionجدول المواقع
كود :
'جدول المواقع
Private Function LoadLoginTable() As DataTable
Dim SelectField As String = "Select Login_Id,SiteName,LoginUrl,usernamee,Passworde,ActionStr,formParams,Inputpass,Inputuser,InputAction From LoginsTb"
LoginDa = New OleDbDataAdapter(SelectField, ConnectionString)
LoginDa.MissingSchemaAction = MissingSchemaAction.AddWithKey
LoginDa.MissingMappingAction = MissingMappingAction.Passthrough
LoginDa.Fill(LoginDataSet, "LoginsTb")
Return LoginDataSet.Tables("LoginsTb")
End Functionبعد ذلك سنقوم بعمل اجراء خاص لفرض العلاقات بين الجداول و نقوم باضافته الى حاوية البيانات MyDataset
تابع الكود التالي
كود :
'فرض العلاقات
Private Sub LoadRelation()
If MyDataset.Tables.Contains("Kind") And MyDataset.Tables.Contains("Coder") And MyDataset.Tables.Contains("Info") And MyDataset.Tables.Contains("post") Then
'علاقة1
Dim KIndColumn As DataColumn = MyDataset.Tables("Kind").Columns("Id")
'علاقة2
Dim CoderColumn As DataColumn = MyDataset.Tables("Coder").Columns("Kind_id")
Dim postidColumn As DataColumn = MyDataset.Tables("post").Columns("id_post")
'علاقة3
Dim postColumn As DataColumn = MyDataset.Tables("post").Columns("id_k")
Dim InfoColumn As DataColumn = MyDataset.Tables("Info").Columns("Id_Kind")
'علاقة4
Dim InfoIdColumn As DataColumn = MyDataset.Tables("Info").Columns("IdInfo")
Dim AttachColumn As DataColumn = MyDataset.Tables("Attach").Columns("Id_inf")
'مسح العلاقات ان وجدت
If MyDataset.Relations.Contains("Kind_Coder") Then
MyDataset.Relations.Remove("Kind_Coder")
End If
'
If MyDataset.Relations.Contains("Kind_post") Then
MyDataset.Relations.Remove("Kind_post")
End If
'
If MyDataset.Relations.Contains("Kind_Info") Then
MyDataset.Relations.Remove("Kind_Info")
End If
'
If MyDataset.Relations.Contains("Info_Attach") Then
MyDataset.Relations.Remove("Info_Attach")
End If
'علاقة الانواع بالاسئلة و الاكواد
Dim Relation1 As New DataRelation("Kind_Coder", KIndColumn, CoderColumn)
MyDataset.Relations.Add(Relation1)
MyDataset.Relations("Kind_Coder").ChildKeyConstraint.UpdateRule = Rule.Cascade
MyDataset.Relations("Kind_Coder").ChildKeyConstraint.DeleteRule = Rule.Cascade
'علاقة الانواع بالفروع
Dim Relation2 As New DataRelation("Kind_post", KIndColumn, postColumn)
MyDataset.Relations.Add(Relation2)
MyDataset.Relations("Kind_post").ChildKeyConstraint.UpdateRule = Rule.Cascade
MyDataset.Relations("Kind_post").ChildKeyConstraint.DeleteRule = Rule.Cascade
'علاقة الفروع بالمقالات
Dim Relation3 As New DataRelation("Kind_Info", postidColumn, InfoColumn)
MyDataset.Relations.Add(Relation3)
MyDataset.Relations("Kind_Info").ChildKeyConstraint.UpdateRule = Rule.Cascade
MyDataset.Relations("Kind_Info").ChildKeyConstraint.DeleteRule = Rule.Cascade
'علاقة المقالات بالمرفقات
Dim Relation4 As New DataRelation("Info_Attach", InfoIdColumn, AttachColumn)
MyDataset.Relations.Add(Relation4)
MyDataset.Relations("Info_Attach").ChildKeyConstraint.UpdateRule = Rule.Cascade
MyDataset.Relations("Info_Attach").ChildKeyConstraint.DeleteRule = Rule.Cascade
End If
End Subالكود بسط جدا ان شاء الله و ساشرحه هنا
- في البداية انا افحص تواجد الجداول داخل Dataset .
- بعدها اقوم بتعريف الاعمدة التي ستقوم بعمليات الربط (المفتاح الرئيسي و المفتاح الثانوي).
- ثم نقوم بمسح العلاقات من Dataset ان وجدت.
- بعدها نقوم بتعريف كائن العلاقة بين جدولين و نسندله المفتاحين في الاب و الابن و نعطي اسم للعلاقة.
- نضيف العلاقة لكائن Dataset .
- ثم نقوم بفرض شرط على العلاقة ان تقوم بعمليات التحديث و الحذف بشكل متزامن بين الجدول الاب و الجدول الابن.
بعد ذلك سنقوم بعمل دالة Function تعيد لنا كائن Dataset معبئ بالجداول و العلاقات كما نحب و نشتهي
كود :
Public Function LoadDataSet() As DataSet
LoadKindTable()
LoadCodeTable()
LoadposterTable()
LoadInfoTable()
LoadAttachTable()
LoadRelation()
'
Return MyDataset
End Functionاضن الكود سهل الهضم و لا يحتاج شرح فهو تجميع للدوال السابقة.
الان ناتي الى اجراء الحفظ الخاص بكل ما جرى على الجداول من حذف و اضافة و تعديل
السيناريو الذي ستعمل معه هو تفحص تغير سجلات القاعدة المؤقته (MyDataset)
و نؤخذ نسخة من كل السجلات التي تعرضت للاضافة او التعديل او الحذف و نرحلها الى قاعدة مؤقته جديدة ساسميها SaveDataset
تحتوي فقط على السجلات المحدثة(مضاف-معدل-محذوف)
ثم سنقوم بارسال التحديثات الى القاعدة الاصل (Access Database)
و بعد الحصول على التحديثات من القاعدة سنقوم بدمج Mydataset مع SaveDataset
وقبول التغيرات الحاصلة .
طريقة سهلة و واضحة و قوية و هي لب الاتصال المنفصل
لنرى ذلك عبر الكود اللذيذ مع الشرح
كود :
Public Sub SaveData()
Try
Dim SaveDataset As New DataSet
SaveDataset = MyDataset.Clone
If MyDataset.HasChanges = True Then
SaveDataset = MyDataset.GetChanges(DataRowState.Added Or DataRowState.Deleted Or DataRowState.Modified)
ComBulder1.DataAdapter = KindDa
ComBulder2.DataAdapter = CodeDa
ComBulder3.DataAdapter = InfoDa
ComBulder4.DataAdapter = PostDa
ComBulder5.DataAdapter = AttachDa
If (Not (SaveDataset) Is Nothing) Then
KindDa.InsertCommand = ComBulder1.GetInsertCommand
KindDa.DeleteCommand = ComBulder1.GetDeleteCommand
KindDa.UpdateCommand = ComBulder1.GetUpdateCommand
'
CodeDa.InsertCommand = ComBulder2.GetInsertCommand
CodeDa.DeleteCommand = ComBulder2.GetDeleteCommand
CodeDa.UpdateCommand = ComBulder2.GetUpdateCommand
'
PostDa.InsertCommand = ComBulder4.GetInsertCommand
PostDa.DeleteCommand = ComBulder4.GetDeleteCommand
PostDa.UpdateCommand = ComBulder4.GetUpdateCommand
'
InfoDa.InsertCommand = ComBulder3.GetInsertCommand
InfoDa.DeleteCommand = ComBulder3.GetDeleteCommand
InfoDa.UpdateCommand = ComBulder3.GetUpdateCommand
'
AttachDa.InsertCommand = ComBulder5.GetInsertCommand
AttachDa.DeleteCommand = ComBulder5.GetDeleteCommand
AttachDa.UpdateCommand = ComBulder5.GetUpdateCommand
End If
KindDa.Update(SaveDataset, "Kind")
CodeDa.Update(SaveDataset, "Coder")
PostDa.Update(SaveDataset, "post")
InfoDa.Update(SaveDataset, "Info")
AttachDa.Update(SaveDataset, "Attach")
MyDataset.Merge(SaveDataset, True, MissingSchemaAction.AddWithKey)
MyDataset.AcceptChanges()
MsgBox("تم الحفظ", MsgBoxStyle.Information + MsgBoxStyle.MsgBoxRight, "حفظ")
End If
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Subالشرح
- تعريف الحاوية المؤقته SaveDataset
- نسخ تخطيط الحاوية MyDataset الى الحاوية SaveDataset فقط نسخ تخطيط الجداول و العلاقات دون نسخ البيانات بمعنى اخر ستتواجد كل الجداول في الحاوية الجديدة مع العلاقات و القيود و التخطيط و كل شيئ باستثاء البيانات.
- الان نفحص وجود تغيرات في الحاوية MyDataset فاذا احتوت تغيرات جديدة منذ اخر استدعاء للطريقة (Acceptchanges) ? تابع شرحها بالاسفل
- اذا كان هناك تغيرات سنقوم باخذ نسخة من هذه التغيرات (الصفوف المضافة و المعدلة و المحذوفة) الى الحاوية SaveDataset.
- بعدها نقول له اذا كانت الحاوية SaveDataset ليست فارغة قم بمايلي:
- سنقوم بتحصيل جمل الادخال و التعديل و الحذف من الكائن CommandBilder بعد اسناده لناقل البيانات الخاص به DataAdapter ? سبق شرحه في الاعلى
- KindDa.Update(SaveDataset, "Kind") هذه الجملة و مابعدها ستقوم بتحديث القاعدة الاصلية (Access Database) كل جدول على حدا
- بعدها سنقوم بدمج التعديلات التي تمت بعد عملية تحديث القاعدة الاصلية وفق الطريقة Merge مع اضافة قيمة المفتاح الاساسي الراجع من القاعدة
- استدعاء الطريقة AcceptChanges و هي التي تعيد حالة MydataSet.HasChanges الى القيمة False بمعنى انها لا تحتوي على تغيرات جديدة يعد اخر عملية حفظ قمنا بها
كود :
Public Function LoadLoginDataSet() As DataSet
LoadLoginTable()
Return LoginDataSet
End Functionو كذلك اجراء الحفظ الخاص به و هو كسابقه الخاص بحفظ التغيرات على الجداول السابقة
كود :
Public Sub SaveLogins()
Try
Dim SaveLoginsDataSet As New DataSet
SaveLoginsDataSet = LoginDataSet.Clone()
If LoginDataSet.HasChanges = True Then
SaveLoginsDataSet = LoginDataSet.GetChanges(DataRowState.Added Or DataRowState.Deleted Or DataRowState.Modified)
'
MsgBox("Hase new Ghange")
ComBulder6.DataAdapter = LoginDa
If (Not (SaveLoginsDataSet) Is Nothing) Then
LoginDa.InsertCommand = ComBulder6.GetInsertCommand
LoginDa.UpdateCommand = ComBulder6.GetUpdateCommand
LoginDa.DeleteCommand = ComBulder6.GetDeleteCommand
'
End If
LoginDa.Update(SaveLoginsDataSet, "LoginsTb")
LoginDataSet.Merge(SaveLoginsDataSet, True, MissingSchemaAction.AddWithKey)
LoginDataSet.AcceptChanges()
MsgBox("تم الحفظ", MsgBoxStyle.Information + MsgBoxStyle.MsgBoxRight, "حفظ")
End If
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Subنفس شرح الكود السابق ؟؟
هكذا نكون قد انتهينا من كلاس الاتصال و الحفظ الخاص بنا
يتبع......
اللهم لك الحمد كما ينبغي لجلال وجهك و عظيم سلطانك
في حل و ترحال


