Sql Server 2008 إغلاق الاتصالات بعد إسقاط قاعدة البيانات

StackOverflow https://stackoverflow.com/questions/821407

سؤال

أواجه مشكلات مع SQL Server الذي يقوم بإسقاط الاتصال بعد أن قمت بإسقاط قاعدة بيانات معينة وإعادة إنشائها، وفي المرة التالية التي أحاول فيها تنفيذ أمر مقابل اتصال جديد على نفس قاعدة البيانات، أحصل على:

حدث خطأ على مستوى النقل عند إرسال الطلب إلى الخادم.(مزود:موفر الذاكرة المشتركة، خطأ:0 - لا توجد عملية على الطرف الآخر من الأنبوب.)

إليك إصدار TCP (إذا حاولت الاتصال بخادم آخر)

حدث خطأ على مستوى النقل عند إرسال الطلب إلى الخادم.(مزود:خطأ في موفر TCP:0 - تم إغلاق الاتصال الموجود بالقوة بواسطة المضيف البعيد.)

فيما يلي خطوات إعادة صياغة المشكلة:

  1. فتح اتصال بقاعدة بيانات وتنفيذ أمر SQL
  2. إسقاط قاعدة البيانات
  3. إعادة إنشاء قاعدة البيانات
  4. افتح اتصالاً جديدًا بنفس قاعدة البيانات وحاول تشغيل أمر ضدها

نتيجة:أتلقى استثناءً

هنا هو الكود:

using (var conn = new System.Data.SqlClient.SqlConnection("Data Source=.;Initial Catalog=DBNAME;Integrated Security=True"))
{
    conn.Open();
    var cmd = conn.CreateCommand();
    cmd.CommandText = "UPDATE ...";
    cmd.ExecuteNonQuery();
}

string sql = "Alter Database DBNAME set single_user with rollback immediate drop database DBNAME";
var server = new Microsoft.SqlServer.Management.Smo.Server(".");
server.ConnectionContext.ExecuteNonQuery(sql);
server.ConnectionContext.Disconnect();

sql = File.ReadAllText("PathToDotSqlFile..."));
server = new Microsoft.SqlServer.Management.Smo.Server(".");
server.ConnectionContext.ExecuteNonQuery(sql);
server.ConnectionContext.Disconnect();

using (var conn = new System.Data.SqlClient.SqlConnection("Data Source=.;Initial Catalog=WER_CONFIG;Integrated Security=True"))
{
    conn.Open();
    var cmd = conn.CreateCommand();
    cmd.CommandText = "UPDATE ...";
    cmd.ExecuteNonQuery();
}

يحدث الخطأ في السطر 'cmd.ExecuteNonQuery()' في النهاية.يبدو أنه على الرغم من أنني أقوم بإنشاء اتصال جديد في كل مرة أقوم فيها بالاتصال، إلا أن خادم SQL يتتبع شيئًا ما (أو ربما رمز ADO.net) حيث في المرة التالية التي أطلب فيها اتصالاً، فإنه يعطيني اتصالًا مستخدمًا بالفعل أو تم إغلاقه من جانب الخادم.لا يدرك أنه تم إغلاقه بواسطة الخادم (ربما بسبب إسقاط قاعدة البيانات المتصلة به) حتى تحاول تنفيذ أمر آخر ضده.

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

لقد حاولت أيضًا استخدام عملية خارجية لإسقاط قاعدة البيانات وإعادة إنشائها كما يلي:

ProcessStartInfo info = new ProcessStartInfo("sqlcmd.exe", " -e -E -S . -Q \"Alter Database DBNAME set single_user with rollback immediate drop database DBNAME\"");
var p = Process.Start(info);
p.WaitForExit();

info = new ProcessStartInfo("sqlcmd.exe", " -i " + PathToDotSqlFile);
p = Process.Start(info);
p.WaitForExit();

وهذا لم يساعد.

هل هناك طريقة لإنشاء SqlConnection جديد والتأكد من أنه نظيف وليس من مجموعة؟هل هناك أي اقتراحات أخرى حول كيفية حل هذه المشكلة؟

تحديث:أدى استخدام SqlConnection.ClearPool() إلى حل المشكلة ولكني اخترت تعديل سلسلة الاتصال الخاصة بي باستخدام Pooling=false والذي نجح أيضًا.

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

المحلول

يقوم ADO.NET تلقائيًا بإدارة تجمع الاتصالات.عندما تقوم "بإغلاق" اتصال في تطبيقك، يتم إعادته إلى التجمع وإبقائه نشطًا، في حالة طلب اتصال بنفس سلسلة الاتصال.قد يكون هذا هو السبب في أن اتصالك "الجديد" قديم.

يمكنك محاولة إيقاف هذا السلوك عن طريق إضافة pooling=false كمعلمة لسلسلة الاتصال الخاصة بك.

نصائح أخرى

لا أعرف شيئًا عن SQL2008، ولكن هذا يبدو وكأنه مشكلة في تجميع الاتصال من جانب التطبيق.في الماضي، أضفنا "OLEDB Services=-1" إلى سلسلة الاتصال لإيقاف تشغيل تجمع الاتصالات.ربما تكون هناك طريقة أكثر أناقة للقيام بذلك الآن.

يحرر:يبدو أن ADO.Net 2.0 أضاف وظيفة ClearPool إلى كائن SQLConnection.(http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.clearpool(VS.80).aspx) أنا مهتم جدًا بمعرفة ما إذا كان هذا يعمل.

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