حسبما أذكر فإنه عند تعريف متغير باستخدام الأمر using فإن البرنامج يقوم بالتخلص من المتغير بعد الخروج من الحلقة
و إذا استخدمناه لتعريف متغير لنقل من النوع SqlConnection أو SqlCommand فمن المفترض به التخلص من ذلك المتغير بعد الخروج من الحلقة
ولكن في واقع الأمر واجهت مشكلة في أحد تطبيقات asp.net مع vb.net التي أقوم بتنفيذها وهي انتهاء عدد الاتصالات المسموحة بقاعدة البيانات
ولدى مراجعة الكود وجدت أنني أستخدم مثلا Return cmd.ExecuteScalar للعودة من الـ Function والخروج من الوظيفة ولكن في الواقع أن الاتصال بقي مفتوحا بعد الخروج من الوظيفة بهذه الطريقة مع أنه نظريا خرج من حلقة using أيضا بواقع الحال
وكان الحل هو أن أسند القيمة إلى متغير ثم أغلق الاتصال يدويا ثم أعيد القيمة بواسطة return
فبرأيكم ما هو الوضع هنا ولماذا واجهت هذا الاشكال
فمع أنني حللت المشكل وأنهيت البرنامج إلا أنه مازالت قضية فكرية عالقة بالنسبة لي
المسألة ليست حالة استثنائية بقدر ماهي تعامل مع مصادر خارج تحكم الفجوال بيسيك نفسه
كما نعلم ان محرك إدارة البيانات مستقل عن الفجوال بيسيك، فعندما يتم طلب فتح الاتصال فان الفجوال بيسيك يرسل الطلب لمحرك إدارة البيانات سواء Access أو SQL Server، وسيضل محسوب هذا الاتصال في المحرك إلا أن تقوم بارسال طلب غلق أو تنتهي المدة المحددة في المحرك في حال عدم وجود نشاط.
من هنا نعلم أنه عند استخدام Using إنما يتم التعامل مع الكائن المنشأ في الفجوال بيسيك فقط، فإذا لم يتم طلب غلق الاتصال وتم الخروج من Using فإن الكائن المنشأ من SqlConnection قد تم تدميره في الفجوال بيسيك وأصبح البرنامج تحت رحمة مدة انتهاء الاتصال الخامل لغلق الاتصال من محرك إدارة البيانات.
لذلك يجب عدم استخدام Return مع اجراءات Execute الخاصة بطلب تنفيذ عملية ما من محرك البيانات وانما يتم وضعها في متغير مثل Dim res = cmd.ExecuteScalar وبعدها يتم طلب إغلاق الاتصال قبل تدمير الكائن SqlConnection ويمكن بعدها ارجاع القيمة مثل Return res
كلام الأخ في الرابط تقريبا نفس فكرة الأخ adham2016
تفسير منطقي من كلا الطرفين
كلام جميل و منطقي ... احب زي هذي المناقشات و الاسئله
شكرا ع الافاده
الأخ سامر
أرجو منك أن تكتب لنا الكود الذي تسبب في المشكلة؟
لأني أعتقد أن المشكلة تكمن في عدم وضوح الرؤية لمتي يتم إستخدام جملة Using
خاصة أن هذه الجملة مصممة للتعامل مع اي كلاس يقوم يكون IDisposable interface جزء منه
أيضا لنضع في الاعتبار أنه لا يمكن تخصيص متغيرات و استردادها أثناء استخدام جملة Using و البديل الأمثل هنا هو استخدام جملة Try Catch Finally End Try خاصة مع الدوال Functions
أو أن يتم بناء كلاس أساسه IDisposable interface
ويكون SqlConnection و Sqlcommand جزء منه بحيث يتم كتابة الدوال داخل الكلاس الجديد ثم و أخيرا يتم اغلاق Connection و عمل Dispsoe لحميع المتغيرات الموجودة في الكلاس الجديد من خلال الحدث Dispsose
و بعد ذلك يمكنك أن تستخدم الكلاس الجديد مع جملة Using بشكل عادي لأنه بعد الانتهاء من جملة using سيتم إغلاق Connection
هذا مثال عن الأكواد التي اتحدث عنها
كما تلاحظ عبارة Try شئ ثابت لدي في أي إجراء أقوم بتنفيذه
كود :
Public Shared Function AddUserActivityRecord(ByVal UsrNam As String, ByVal FormName As String, ByVal OperationExecuted As String,
ByVal OPER_DESCR As String) As Integer
Try
Using con As New SqlConnection(ConfigurationManager.ConnectionStrings("JoyBoxStaff").ConnectionString)
Dim cmd As New SqlCommand()
cmd.Connection = con
cmd.CommandText = "INSERT INTO USER_ACTIVITY (USER_NAME, FORM_NAME, OPERATION_EXECUTED, DATE_AND_TIME, OPERATION_DESCRIPTION) "
cmd.CommandText &= "VALUES (@USR, @FRN, @OPX, @DTM, @OPERATION_DESCRIPTION)"
cmd.Parameters.Add("@USR", Data.SqlDbType.NVarChar).Value = UsrNam
cmd.Parameters.Add("@FRN", Data.SqlDbType.NVarChar).Value = FormName
cmd.Parameters.Add("@OPX", Data.SqlDbType.NVarChar).Value = OperationExecuted
cmd.Parameters.Add("@DTM", SqlDbType.DateTime2, 7).Value = DateTime.Now
cmd.Parameters.Add("@OPERATION_DESCRIPTION", Data.SqlDbType.NVarChar).Value = OPER_DESCR
cmd.Connection.Open()
Return cmd.ExecuteNonQuery()
cmd.Connection.Close()
End Using
Catch ex As Exception
Return -10
End Try
End Function
بعد رؤية الدالة المستخدمة أعقتد أن كيفية و اسلوب كتابة الكود وخاصة مع جملة Using لا يصلح معه ان نسترد من خلاله أي متغيرات
جملة Using قد تكلفك الكثير في تلك الحالة و البدبل الأمثل جملة Try Catch Finally End Try
أو ان كان ضروريا أن تستخدم جملة Using تحديدا في تلك الحالة انت تحتاج لبناء كلاس منفرد تضع به جميع الدوال و يكون اساسه IDisposable Interface
عموما أن أردت يمكنني ان أضع لك الكود الخاص بهذا الكلاس لاحقا و عليك أنت أن تكمل بناء الكلاس و تضيف له الدوال التي تريدها
ياريت لو تضع لنا مثالا يوضح فكرة الكلاس الذي تتحدث عنه