سؤال

أحاول عمل نسخة من قاعدة البيانات إلى قاعدة بيانات جديدة على نفس الخادم.الخادم هو جهاز الكمبيوتر المحلي الخاص بي الذي يعمل بنظام SQL 2008 Express ضمن نظام التشغيل Windows XP.يجب أن يكون القيام بذلك أمرًا سهلاً للغاية باستخدام فئة SMO.Transfer وهو يعمل تقريبًا!

الكود الخاص بي هو كما يلي (مبسط إلى حد ما):

Server server = new Server("server");
Database sourceDatabase = server.Databases["source database"];

Database newDatbase = new Database(server, "new name");
newDatbase.Create();

Transfer transfer = new Transfer(sourceDatabase);
transfer.CopyAllObjects = true;
transfer.Options.WithDependencies = true;
transfer.DestinationDatabase = newDatbase.Name;
transfer.CopySchema = true;
transfer.CopyData = true;
StringCollection transferScript = transfer.ScriptTransfer();

using (SqlConnection conn = new SqlConnection(connectionString))
{
    conn.Open();
    using (SqlCommand switchDatabase = new SqlCommand("USE " + newDatbase.Name, conn))
    {
        switchDatabase.ExecuteNonQuery();
    }

    foreach (string scriptLine in transferScript)
    {
        using (SqlCommand scriptCmd = new SqlCommand(scriptLine, conn, transaction))
        {
            int res = scriptCmd.ExecuteNonQuery();
        }
    }
}

ما أفعله هنا هو إنشاء قاعدة بيانات جديدة أولاً، ثم إنشاء نسخة نصية باستخدام ملف Transfer class وأخيراً تشغيل البرنامج النصي في قاعدة البيانات الجديدة.

هذا يعمل بشكل جيد لنسخ الهيكل، ولكن CopyData الخيار لا يعمل!

هل هناك أي حدود غير موثقة ل CopyData خيار؟تقول الوثائق فقط أن الخيار يحدد ما إذا كان سيتم نسخ البيانات أم لا.

حاولت استخدام TransferData() طريقة لنسخ قاعدة البيانات دون استخدام برنامج نصي ولكن بعد ذلك أحصل على استثناء يقول "فشل الاتصال بالخادم" مع استثناء داخلي يقول "حدث خطأ متعلق بالشبكة أو خطأ خاص بالمثيل أثناء إنشاء اتصال بـ SQL Server.لم يتم العثور على الخادم أو لم يكن من الممكن الوصول إليه.تحقق من صحة اسم المثيل ومن تكوين SQL Server للسماح بالاتصالات عن بعد.(مزود:موفر توجيهات الإخراج المسمى، خطأ:40 - تعذر فتح اتصال بـ SQL Server)"

لقد حاولت أيضًا تمكين Named Pipes على الخادم، لكن ذلك لم يساعد.

يحرر:لقد وجدت حلاً يعمل عن طريق عمل نسخة احتياطية ثم استعادتها إلى قاعدة بيانات جديدة.إنه أمر أخرق تمامًا، وأبطأ مما ينبغي، لذلك ما زلت أبحث عن حل أفضل.

هل كانت مفيدة؟

المحلول

حسنا، بعد الاتصال دعم برامج Microsft حصلت عليه تعمل بشكل صحيح، لكنه بطيء وأكثر أو أقل لا طائل منه. القيام نسخة احتياطية ثم استعادة أسرع بكثير وسوف يكون استخدامه طالما النسخة الجديدة يجب أن يعيش على نفس الخادم الأصلي.

وكود العمل هو كما يلي:

ServerConnection conn = new ServerConnection("rune\\sql2008");
Server server = new Server(conn);

Database newdb = new Database(server, "new database");
newdb.Create();

Transfer transfer = new Transfer(server.Databases["source database"]);
transfer.CopyAllObjects = true;
transfer.CopyAllUsers = true;
transfer.Options.WithDependencies = true;
transfer.DestinationDatabase = newdb.Name;
transfer.DestinationServer = server.Name;
transfer.DestinationLoginSecure = true;
transfer.CopySchema = true;
transfer.CopyData = true;
transfer.Options.ContinueScriptingOnError = true;
transfer.TransferData();

وكانت خدعة لتعيين الخاصية DestinationDatabase. هذا يجب أن يتم تعيين حتى لو كان الهدف هو أن نفس المصدر. وبالإضافة إلى ذلك اضطررت للاتصال الملقم ك مثيل مسمى بدلا من استخدام خيارات اتصال أخرى.

نصائح أخرى

وكان لي الذهاب في الحصول على هذا العمل وقد حان حتى مع جوابا التي لا تستخدم طبقة النقل. هنا هو الطريقة اعتدت:

       public bool CreateScript(string oldDatabase, string newDatabase)
   {
       SqlConnection conn = new SqlConnection("Data Source=.;Initial Catalog=" + newDatabase + ";User Id=sa;Password=sa;");
       try
       {
           Server sv = new Server();
           Database db = sv.Databases[oldDatabase];

           Database newDatbase = new Database(sv, newDatabase);
           newDatbase.Create(); 

           ScriptingOptions options = new ScriptingOptions();
           StringBuilder sb = new StringBuilder();
           options.ScriptData = true;
           options.ScriptDrops = false;
           options.ScriptSchema = true;
           options.EnforceScriptingOptions = true;
           options.Indexes = true;
           options.IncludeHeaders = true;
           options.WithDependencies = true;

           TableCollection tables = db.Tables;

           conn.Open();
           foreach (Table mytable in tables)
           {
               foreach (string line in db.Tables[mytable.Name].EnumScript(options))
               {
                   sb.Append(line + "\r\n");
               }
           }
           string[] splitter = new string[] { "\r\nGO\r\n" };
           string[] commandTexts = sb.ToString().Split(splitter, StringSplitOptions.RemoveEmptyEntries);
           foreach (string command in commandTexts)
           {
               SqlCommand comm = new SqlCommand(command, conn);
               comm.ExecuteNonQuery();
           }
           return true;
       }
       catch (Exception e)
       {
           System.Diagnostics.Debug.WriteLine("PROGRAM FAILED: " + e.Message);
           return false;
       }
       finally
       {
           conn.Close();
       }
   }

حاول الإعداد SetDefaultInitFields لصحيح على الخادم هدف.

واجهت نفس المشكلة مع كائن قاعدة بيانات SMO الذي يعمل ببطء.أعتقد أن السبب في ذلك هو أن خادم SQL لا يحب استرداد الكائنات والمجموعات بأكملها مرة واحدة، وبدلاً من ذلك يقوم بتحميل كل شيء كسولًا، مما يتسبب في رحلة ذهابًا وإيابًا لكل حقل، وهو أمر غير فعال إلى حد ما بالنسبة لقاعدة البيانات بأكملها.

هنا هو الحل الخاص بي:

  1. لدي قاعدة بيانات اسمها Olddatabase
  2. أقوم بعمل نسخة احتياطية منه على E:\databackup\Old.bak

  3. إذا كنت تريد إنشاء قاعدة بيانات مكررة من Olddatabase في نفس الخادم بالاسم NewDatabase

3.1 يمكنك استخدام الأمر في أداة الاستعلام:EXEC OldDatabase.dbo.sp_helpfile;لتحديد مسار OldDatabase الذي يتم تخزينه في حالة رغبتك في حفظ NewDatabase في نفس المجلد.

أو يمكنك حفظ NewDatabase في المسار الجديد الذي تريده

  1. استخدم هذا الأمر في أداة الاستعلام

    استعادة قاعدة بيانات NewDatabase من Disk = 'e: databackup old.bak' مع التحرك 'OldDatabase' إلى 'e: new path (أو نفس المسار) المسار (أو نفس المسار) newdatabase_log.ldf '؛

ملحوظة:يمكنك استخدام هذه الأوامر أعلاه في c# مع:إنشاء إجراء مخزن في SQL والذي يتضمن الأوامر أعلاه.ويمكنك استدعاء إجراء المتجر في C #

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top