بسم الله الرحمن الرحيم
الحمد لله أخيرا وبعد اكثر من ثلاثة أشهر من البحث وجدت طريقة لتثبيت قاعدة البيانات على SQL SERVER وذلك عند تثبيت برنامجك( (Setup وفي نظري اسهل طريقة هي هذه لانها لا تتطلب منك كتابة سكريبتات لعمل القاعدة والجداول والاجراءات المخزنة وانما بعد ان تنتهي من مشروعك تقوم بعمل Attach لقاعدة البيانات من SQL SERVER ومن ثم تبدأ ببرمجة برنامج التنصيب لكي يكمل المشوار (نسخ قاعدة البيانات الى C: مثلا ومن ثم عمل Attach لها ) بعد ان تنتهي, تقوم بنسخ الملفات كاملة الى CD وبذلك تكون انتهيت....و انحلت القضية( أخذت مني حوالي اربع ساعات من التجارب الفاشلة)
المهم سوف ابدأ بشرح الطريقة وكذلك ارفقت المثال مع المشاركة
في البداية عليك بفتح مشروع جديد من نوع Class Library
ثم انقر على المشروع باليمين من نافذة Solution Explorer
واختر Add – Add New Item
من النافذة اختر Installer Class
بعد ذلك قم بإضافة SqlConnection الى Installer Class
وحدد قاعدة البيانات Master واسم الخادم localhost بحيث يشتغل على جهاز العميل
ثم اضف الاتي في بداية الملف Installer Class
Imports System.IO Imports System.Reflection
واضف الاتي قبل End Class في Installer Class ايضا
Private Function GetSql(ByVal Name As String) As String
Try
' Gets the current assembly.
Dim Asm As [Assembly] = [Assembly].GetExecutingAssembly()
' Resources are named using a fully qualified name.
Dim strm As Stream = Asm.GetManifestResourceStream(Asm.GetName().Name + "." + Name)
' Reads the contents of the embedded file.
Dim reader As StreamReader = New StreamReader(strm)
Return reader.ReadToEnd()
Catch ex As Exception
MsgBox("In GetSQL: " & ex.Message)
Throw ex
End Try
End Function
Private Sub ExecuteSql(ByVal DatabaseName As String, ByVal Sql As String)
Dim Command As New SqlClient.SqlCommand(Sql, SqlConnection1)
Command.Connection.Open()
Command.Connection.ChangeDatabase(DatabaseName)
Try
Command.ExecuteNonQuery()
Finally
' Finally, blocks are a great way to ensure that the connection
' is always closed.
Command.Connection.Close()
End Try
End Sub
Protected Sub AddDBTable(ByVal strDBName As String)
Try
'Select the last drive in your PC & assign it to Drv (CD-ROM By default)
Dim strDrive As String
Dim Drv As String
For Each strDrive In Directory.GetLogicalDrives()
Drv = strDrive
Next
'للتأكد من وجود الملفات في الاسطوانة
If File.Exists(Drv & "Database1_Data.mdf") = True Then
' .mdf نسخ ملفات
Dim fi As FileInfo = New FileInfo(Drv & "Database1_Data.mdf")
fi.CopyTo("C:\Database1_Data.mdf", True)
'تحويل خصائص الملف الى الطبيعية
File.SetAttributes("C:\Database1_Data.mdf", FileAttributes.Normal)
' .ldf نسخ ملفات
fi = New FileInfo(Drv & "Database1_Log.ldf")
fi.CopyTo("C:\Database1_Log.ldf", True)
'تحويل خصائص الملف الى الطبيعية
File.SetAttributes("C:\Database1_Log.ldf", FileAttributes.Normal)
' تثبيت قاعدة البيانات
ExecuteSql("master", "sp_attach_db MyDB , @filename1 = 'C:\Database1_Data.mdf'")
' C:\ اذا لم يستطع البرنامج تحديد موقع الملفات فعليك نسخها يدويا الى
Else
MsgBox(" C:\ الرجاء نسخ ملفات قاعدة البيانات يدويا الى ", MsgBoxStyle.Information)
MsgBox(" C:\Database1_Data.mdf الرجاء التأكد من وجود الملف ", MsgBoxStyle.Information)
' تثبيت قاعدة البيانات
ExecuteSql("master", "sp_attach_db MyDB , @filename1 = 'C:\Database1_Data.mdf'")
End If
Catch ex As Exception
' Reports any errors and abort.
MsgBox("In exception handler: " & ex.Message, MsgBoxStyle.Information, "خطأ في تثبيت قاعدة البيانات")
Throw ex
End Try
End Sub
Public Overrides Sub Install(ByVal stateSaver As System.Collections.IDictionary)
MyBase.Install(stateSaver)
AddDBTable(Me.Context.Parameters.Item("dbname"))
End Subالان عليك باضافة مشروع من نوع Setup
طبعا من القائمة File – Add Project – New Project
وسمه كما اردت
ثم في المجلد Application Folder الظاهر امامك انقر عليه باليمين واختر Add
ثم Project Output
اختر Primary Output من List
وانقر OK
بعد ذلك قم بالنقر باليمين على مشروع Setup من Solution Explorer
واختر View ثم Custom Actions
في النافذة التى ظهرت انقر باليمين على Install واختر Add Custom Action
وحدد المجلد Application Folder واختر الملف الظاهر (والذي قمنا بانشاءه في السابق) سيكون اسمه Primary output from attachDatabase(Active)
الان قم ببناء المشروعين من القائمة Build
وتأكد من عمل البرنامج بتشغيل ال Setup من المجلد الذي حددته من قبل
وإن شاء الله يشتغل معاك
ملاحظة:
• المثال المرفق يقوم بتثبيت قاعدة البيانات واسمها MyDB الى السيرفر من الCD-ROM واذ لم تكن موجودة فعليك نسخها الى C:\ وتجريب البرنامج
• الاسم الاساسي للقاعدة هو Database1 واسم الملف Database1_data.mdf
• كذلك الامر المستخدم لتثبيت القاعدة هو
sp_attach_db MyDB,@filename1 = 'C:\Database.mdf'
وهو في الاصل اجراء مخزن في القاعدة Master لتثبيت قواعد البيانات يدويا
واذا اردت تحسين البرنامج مثلا عند Uninstall تريد ان يتم فصل قاعدة البيانات من السيرفر والامر سهل جدا
sp_detach_db MyDB,TRUE
• مثلا اذا كان العميل لا يملك SQL SERVER فما العمل؟
هناك MSDE اختصارا لـ Microsoft Desketop Engine ويعتبر اللب او نسخة محدودة الامكانيات من SQL SERVER ولكن يمكنك من عمل Queries , Insert , Update,….
ويأتي هذا البرنامج مع اسطوانة Office أو يمكنك تحميله من microsoft.com
• كذلك اريد ان انبه على قضية النسخ الى C:\ قد يسأل سائل ويقول لماذ لا نختصر المسألة ونعمل تثبيت القاعدة من الاسطوانة بدون نسخها الى السي
والجواب هو انه لو اتبعنا هذه الطريقة ستكون القاعدة ReadOnly لانستطيع اضافة اي سجلات اليها وهذا لا نريده ( الا في حالة استخدمنا هذه القاعدة للقراءة فقط !!!)
• ولو تلاحظوا في الكود انه يقوم بعد النسخ بتغير خصائص الملف .mdf والملف .ldf الى Normal لانه عندما نسختهم الى الجهاز من الاسطوانة تكون خصائصهم ReadOnly
ولا اعتقد ان هناك ضرورة لشرح الكود مفصلا لان ال Comments كافية وان كان في اي اسئلة إن شاء الله سوف احاول الاجابة عليها ولا أخفيكم ان لدي نية بعمل شرح مرئي للمثال السابق ولكن لا اعدكم بشيء اخاف ان لا استطيع الوفاء به
• المراجع:
- MP SQL SERVER 2000 System Administration (70-229) Page-195
- MCAD/MCSD Exam Study Guide (All-in-One) Chapter 19
- MP Developing Windows-Based Apps with VB.NET (70-306) Chapter 10
