วันนี้ แบบสอบถามจำเป็นต้องส่งคืนชุดผลลัพธ์ผ่าน ExcuteReader และในขณะเดียวกันก็ต้องการส่งพารามิเตอร์เอาต์พุต ในตอนแรก ฉันไม่สามารถรับค่าของพารามิเตอร์เอาต์พุตได้ เนื่องจากคิดว่าขั้นตอนการจัดเก็บมีข้อผิดพลาด การทดสอบในตัววิเคราะห์แบบสอบถามนั้นถูกต้อง และพารามิเตอร์เอาต์พุตก็เปลี่ยนไปจริงๆ
สิ่งที่น่าสงสัยยิ่งกว่านั้นคือหลังจากส่งข้อยกเว้นระหว่างการแปลงประเภทบังคับแล้ว มันสามารถได้รับอีกครั้งอย่างแน่นอน มันเป็นข้อผิดพลาดของ ado.net หรือไม่ มันเป็นไปไม่ได้สำหรับสิ่งนี้ API ที่ใช้กันทั่วไปเพื่อให้ปรากฏขึ้น รหัสของฉันคล้ายกับสถานการณ์ต่อไปนี้:
ลอง {
การใช้ (SqlDataReader dr = cmd.ExecuteReader (CommandBehavior.CloseConnection)) {
int val = (int)cmd.Parameters[1].Value; // ตอนนี้ยังว่างเปล่า
// มากกว่า
-
-
catch (ประสบการณ์ข้อยกเว้น) {
โยน ApplicationException ใหม่ ("ค่าพารามิเตอร์เอาต์พุต: " + cmd.Parameters [1].Value, exp); // ตอนนี้สามารถรับค่าเอาต์พุตได้
}
มันน่าหงุดหงิดจริงๆ หลังจากแก้ไขจุดบกพร่องและติดตามเป็นเวลาหนึ่งชั่วโมง
ในที่สุดฉันก็พบคำตอบใน MSDN:
เมื่อคุณใช้วัตถุ Command กับ Stored Procedure คุณสามารถตั้งค่าคุณสมบัติ CommandType ของวัตถุ Command เป็น StoredProcedure ได้ เมื่อ CommandType เป็น StoredProcedure คุณสามารถใช้คุณสมบัติพารามิเตอร์ของ Command เพื่อเข้าถึงพารามิเตอร์อินพุตและเอาต์พุตและส่งกลับค่าได้ ไม่ว่าจะเรียกเมธอด Execute ใดก็ตาม คุณสามารถเข้าถึงคุณสมบัติพารามิเตอร์ได้ อย่างไรก็ตาม เมื่อเรียกใช้ ExecuteReader ค่าที่ส่งคืนและพารามิเตอร์เอาต์พุตจะไม่สามารถเข้าถึงได้จนกว่า DataReader จะปิด
ref: http://msdn2.microsoft.com/zh-CN/library/tyy0sz6b.aspx
แค่นั้นแหละ ฉันรู้สึกเหมือนถูก MS หลอกอีกครั้ง ลองคิดดูสิว่าทำไมฉันถึงไม่มีประสบการณ์ในการเรียนรู้ ได้เปลี่ยนเอกสารแล้วและ
กลับสู่เอกสารนั้นอีกครั้ง ยังสามารถอธิบายสภาพแวดล้อมโค้ดของคุณเองได้
เนื่องจากเมื่อตรวจพบข้อยกเว้น ขอบเขตการใช้งานได้ถูกข้ามออกไป DataReader ได้ถูกปิดโดยอัตโนมัติ และสามารถรับค่าของพารามิเตอร์เอาต์พุตได้ตามธรรมชาติ
แน่นอน หากคุณลองใช้งาน คุณจะยังคงไม่สามารถรับมันได้ เนื่องจากยังอยู่ในขอบเขตการใช้งานและ DataReader ยังไม่ได้ถูกปิด
นอกจากนี้ MSDN ยังบอกว่าสามารถเข้าถึงได้เฉพาะในกรณีที่ DataReader ปิดอยู่ แต่ไม่ได้เป็นเช่นนั้น
หลังจากทดสอบแล้วสรุปได้ดังนี้
1. สำหรับ ExecuteReader พาร์มเอาท์พุตและค่าที่ส่งคืนจะถูกส่งกลับไปยัง DataReader เป็นชุดผลลัพธ์ และชุดผลลัพธ์จะเป็นชุดสุดท้ายเสมอ
2. ตามข้อ 1 เมื่อมีการตั้งค่าผลลัพธ์ ในการเข้าถึงพารามิเตอร์เอาต์พุตและค่าที่ส่งคืน คุณต้องเรียก NextResult ไปยังตำแหน่งชุดผลลัพธ์ที่สอดคล้องกับพารามิเตอร์เอาต์พุตและค่าที่ส่งคืน
3. ตามข้อ 1 เมื่อ Execute ไม่ส่งคืนชุดผลลัพธ์ ก็สามารถเข้าถึงได้โดยตรง (โปรดทราบว่าไม่จำเป็นต้องเรียก Read())
4. ให้ความสนใจเป็นพิเศษกับความจำเป็นในการเรียก NextResult หลายครั้งหากมีการส่งคืนชุดผลลัพธ์หลายชุด หากจำนวนชุดผลลัพธ์เป็นแบบไดนามิก ค่าที่ส่งคืนของ nextResult() จะเป็นเท็จ
5. แม้ว่าตัวเลือก CommandBehavior.SingleResult จะถูกระบุสำหรับ ExecuteReader (การส่งคืนชุดผลลัพธ์เดียว อันที่จริงเป็นการส่งคืนชุดผลลัพธ์ชุดแรกของแบตช์) พารามิเตอร์เอาต์พุตจะถูกส่งกลับเป็นชุดผลลัพธ์
6. เมื่อปิด DataReader (ปิด()) พารามิเตอร์เอาต์พุตจะถูกเติมและสามารถเข้าถึงได้
7. เนื่องจาก DataReader เป็นแบบอ่านไปข้างหน้าเท่านั้น แม้ว่าจะได้รับพารามิเตอร์เอาต์พุตผ่านเมธอด NextResult ก่อนที่จะปิด DataReader ชุดผลลัพธ์ก่อนหน้าจะไม่สามารถเข้าถึงได้อีกต่อไป (ในบางกรณี คุณอาจต้องการควบคุมชุดผลลัพธ์แบบไดนามิกผ่านเอาต์พุต พารามิเตอร์การเยี่ยมชม)
8. เพื่อที่จะแก้ไขปัญหาใน 6 คุณไม่สามารถใช้พารามิเตอร์เอาต์พุตและส่งคืนพารามิเตอร์เอาต์พุตโดยตรงเป็นผลลัพธ์แรก (SELECT @parmname)
ข้างต้นเป็นเพียงบทสรุปของฉันเอง ฉันหวังว่าจะไม่มีความแตกต่างและอาจเป็นเช่นนั้น เป็นประโยชน์สำหรับผู้เริ่มต้น
อ้างอิง:
http://www.bigcircleboy.net/583a194f-2c2c-4662-9036-4e2f0eb262396084313157728108.html