اليوم، يحتاج الاستعلام إلى إرجاع مجموعة النتائج من خلال ExcuteReader، وفي الوقت نفسه يريد إخراج المعلمات في البداية، لم أتمكن من الحصول على قيمة معلمات الإخراج، معتقدًا أن الإجراء المخزن به خطأ. كان الاختبار في محلل الاستعلام صحيحًا، وتم تغيير معلمات الإخراج بالفعل.
والأمر الأكثر إثارة للحيرة هو أنه بعد طرح استثناء أثناء تحويل النوع القسري للمخرجات، هل من الممكن بالفعل الحصول عليه مرة أخرى؟ هل تظهر واجهة برمجة التطبيقات شائعة الاستخدام؟ هل هذا خطأ؟ الكود الخاص بي مشابه للسيناريو التالي:
حاول {
باستخدام (SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection)) {
int val = (int)cmd.Parameters[1].Value; // لا يزال فارغًا الآن
// أكثر
}
}
قبض على (استثناء إكسب) {
throw new ApplicationException("قيمة معلمة الإخراج:" + cmd.Parameters[1].Value, exp);
}
إنه أمر محبط حقًا، وبعد التصحيح والتتبع لمدة ساعة،
وجدت الإجابة أخيرًا في MSDN:
عند استخدام كائن Command مع إجراء مخزن، يمكنك تعيين خاصية CommandType لكائن Command إلى StoredProcedure. عندما يكون CommandType هو StoredProcedure، يمكنك استخدام خاصية معلمات الأمر للوصول إلى معلمات الإدخال والإخراج وإرجاع القيم. بغض النظر عن أسلوب التنفيذ الذي يتم استدعاؤه، يمكن الوصول إلى خاصية المعلمات. ومع ذلك، عند استدعاء ExecuteReader، لن يكون من الممكن الوصول إلى قيمة الإرجاع ومعلمات الإخراج حتى يتم إغلاق DataReader.
المرجع: http://msdn2.microsoft.com/zh-CN/library/tyy0sz6b.aspx
هذا كل شيء، أشعر وكأنني قد خدعت من قبل مرض التصلب العصبي المتعدد مرة أخرى لقد قمت بالفعل بتغيير المستند
والعودة إليه ولا يزال من الممكن شرح بيئة التعليمات البرمجية الخاصة بك.
لأنه عندما يتم اكتشاف الاستثناء، يتم القفز إلى نطاق الاستخدام، ويتم إغلاق DataReader تلقائيًا، ويمكن الحصول على قيمة معلمة الإخراج بشكل طبيعي.
بالطبع، إذا قمت بوضع المحاولة في الاستخدام، فلا يزال يتعذر عليك الحصول عليها، لأنها لا تزال في نطاق الاستخدام ولم يتم إغلاق DataReader.
بالإضافة إلى ذلك، تقول MSDN أنه لا يمكن الوصول إليها إلا إذا كان DataReader مغلقًا، ولكن هذا ليس هو الحال.
وبعد الاختبار يمكن تلخيصها بما يلي:
1. بالنسبة إلى ExecuteReader، يتم إرجاع قيمة الإخراج وقيمة الإرجاع إلى DataReader كمجموعة نتائج، وتكون مجموعة النتائج دائمًا هي الأخيرة.
2. وفقًا للرقم 1، عندما تكون هناك مجموعة نتائج، للوصول إلى معلمات الإخراج وقيم الإرجاع، تحتاج إلى استدعاء NextResult إلى موقع مجموعة النتائج المطابق لمعلمات الإخراج وقيم الإرجاع.
3. وفقًا للرقم 1، عندما لا يُرجع Execute مجموعة نتائج، يمكن الوصول إليها مباشرة (لاحظ أنه ليست هناك حاجة للاتصال بـ Read())
4. انتبه بشكل خاص إلى الحاجة إلى استدعاء NextResult عدة مرات إذا تم إرجاع مجموعات نتائج متعددة؛ إذا كان عدد مجموعات النتائج ديناميكيًا، فستكون قيمة الإرجاع لـ nextResult() خاطئة.
5. حتى إذا تم تحديد الخيار CommandBehavior.SingleResult لـ ExecuteReader (إرجاع مجموعة نتائج واحدة، في الواقع، إرجاع مجموعة النتائج الأولى من الدفعة)، يتم إرجاع معلمات الإخراج كمجموعة نتائج.
6. عند إغلاق DataReader (Close())، يتم ملء معلمات الإخراج وبالتالي يمكن الوصول إليها.
7. نظرًا لأن DataReader للقراءة فقط، حتى إذا تم الحصول على معلمات الإخراج من خلال طريقة NextResult قبل إغلاق DataReader، فلا يمكن الوصول إلى مجموعة النتائج السابقة بعد الآن (في بعض الحالات، قد ترغب في التحكم ديناميكيًا في مجموعة النتائج من خلال الإخراج المعلمات .
8. من أجل حل المشكلة في 6، لا يمكنك استخدام معلمة الإخراج وإرجاع معلمة الإخراج مباشرة كنتيجة أولى (SELECT @parmname).
ما ورد أعلاه هو مجرد ملخص خاص بي، وآمل ألا يكون هناك تناقض مفيدة للمبتدئين.
المرجع:
http://www.bigcircleboy.net/583a194f-2c2c-4662-9036-4e2f0eb262396084313157728108.html