هل SQLCommand.Dispose () مطلوب إذا تم التخلص من SQLConnection المرتبطة؟
-
05-07-2019 - |
سؤال
عادة ما أستخدم رمز مثل هذا:
using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString))
{
var command = connection.CreateCommand();
command.CommandText = "...";
connection.Open();
command.ExecuteNonQuery();
}
سوف بلدي command
التخلص تلقائيا؟ أو لا يجب أن ألفها using
الكتلة؟ هل هو مطلوب للتخلص منه SqlCommand
?
المحلول
فقط افعل هذا:
using(var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString))
using(var command = connection.CreateCommand())
{
command.CommandText = "...";
connection.Open();
command.ExecuteNonQuery();
}
عدم الاتصال بالتخلص من الأمر لن يفعل أي شيء سيء للغاية. ومع ذلك ، فإن الاتصال بالتخلص منه سوف قم بتجميع المكالمة إلى Finalizer, جعل الاتصال التخلص من تعزيز الأداء.
نصائح أخرى
السياسة الأكثر أمانًا هي الاتصال دائمًا Dispose()
على كائن إذا كان ينفذ IDisposable
, ، إما بشكل صريح أو عبر كتلة باستخدام. قد تكون هناك حالات غير مطلوبة ولكن تسميتها على أي حال يجب ألا تسبب مشاكل (إذا تم كتابة الفصل بشكل صحيح). أيضًا ، لا تعرف أبدًا متى قد يتغير التنفيذ بمعنى أنه عندما لم تكن المكالمة مطلوبة من قبل ، فمن المؤكد أنها مطلوبة الآن.
في المثال الذي قدمته ، يمكنك إضافة إطار إضافي باستخدام كتلة للأمر ، وكذلك الحفاظ على الخارجي باستخدام كتلة للاتصال.
نعم ، يجب عليك ، حتى لو كان التنفيذ لا يفعل الكثير حاليًا ، فأنت لا تعرف كيف سيتم تغييره في المستقبل (إصدارات إطار عمل أحدث على سبيل المثال). بشكل عام ، يجب عليك التخلص من جميع الكائنات التي تنفذ IDisposable
أن تكون على الجانب الآمن.
ومع ذلك ، إذا تم تأجيل العملية ولم تتحكم في النطاق الكامل (على سبيل المثال عند العمل بشكل غير متزامن ، أو عند إرجاع AN SqlDataReader
أو هكذا) ، يمكنك تعيين ملف CommandBehavior
إلى CloseConnection
حتى أنه بمجرد الانتهاء من القارئ ، يتم إغلاق الاتصال/التخلص من ذلك بشكل صحيح.
يمكنك معرفة هذا النوع من الأشياء باستخدام العاكس أو dotpeek أو https://referencesource.microsoft.com/.
كان لدي حفر صغير (أود أن أقترح أن تحفر نفسك على الرغم من أن تكون متأكدًا تمامًا من بقية هذا على الرغم من أنني لم أحاول ذلك بجد) ويبدو أنه عندما تقتل اتصال لا يوجد أي أطفال مرتبطون مع هذا الاتصال. علاوة على ذلك ، لا يبدو في الواقع أن التخلص من الأمر يفعل ذلك كثيرًا. سيتم تعيين حقل لتفريغه ، وفصل نفسه عن حاوية (قد يمنع هذا تسرب الذاكرة المدارة) ورفع حدث (قد يكون هذا مهمًا ولكن لا يمكنني رؤية من يستمع إلى هذا الحدث).
في كلتا الحالتين ، من الممارسات الجيدة استخدام هذه الأشياء في كتلة باستخدام أو التأكد من التخلص منها باستخدام نمط التخلص في الكائن الذي يحمل الاتصال (إذا كنت تنوي التمسك بالأمر لفترة من الوقت).
في الممارسة العملية ، يمكنك تخطي Dispose
. إنه لا يحرر أي موارد. حتى أنه لا يقمع الانتهاء منذ SQLCommand Constructor يفعل ذلك.
من الناحية النظرية ، يمكن لـ Microsoft تغيير التنفيذ لعقد مورد غير مُدار ، لكنني آمل أن يخرجوا مع واجهة برمجة تطبيقات تتخلص من Component
الفئة الأساسية قبل وقت طويل من القيام بذلك.
في رأيي ، الدعوة Dispose
لكليهما SqlConnection
و SqlCommand
هي الممارسة الجيدة ، استخدم الكود أدناه
using(var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString))
try{
using(var command = connection.CreateCommand())
{
command.CommandText = "...";
connection.Open();
command.ExecuteNonQuery();
}
}
catch(Exception ex){ //Log exception according to your own way
throw;
}
finally{
command.Dispose();
connection.Close();
connection.Dispose();
}