سؤال

ما هي أفضل طريقة لتمرير المعلمات إلى SQLCommand؟يمكنك ان تفعل:

cmd.Parameters.Add("@Name", SqlDbType.VarChar, 20).Value = "Bob";

أو

cmd.Parameters.Add("@Name", SqlDbType.VarChar).Value = "Bob";

أو

cmd.Parameters.Add("@Name").Value = "Bob";

يبدو أن الأول قد يكون "أفضل" بطريقة أو بأخرى سواء من حيث الأداء أو التحقق من الأخطاء.ولكن أود أن أعرف بشكل أكثر تحديدا.

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

المحلول

ويمكنك أيضا استخدام AddWithValue()، ولكن يكون على بينة من إمكانية الخطأ نوع التحويل الضمني.

cmd.Parameters.AddWithValue("@Name", "Bob");

نصائح أخرى

ماذا يحدث هناك؟

يمكنك اقتباس قوائم المعلمات لعدة حمولات زائدة Add.هذه هي أساليب الراحة التي تتوافق مباشرة مع التحميل الزائد للمنشئ لـ SqlParameter فصل.يقومون بشكل أساسي بإنشاء كائن المعلمة باستخدام أي مُنشئ له نفس التوقيع مثل الطريقة الملائمة التي اتصلت بها، ثم الاتصال SqlParameterCollection.Add(SqlParameter) مثله:

SqlParameter foo = new SqlParameter(parameterName, dbType, size);
this.Add(foo);

AddWithValue مشابه ولكنه يأخذ الراحة إلى أبعد من ذلك، ويحدد القيمة أيضًا.ومع ذلك، فقد تم تقديمه بالفعل لحل خلل في إطار العمل.على حد تعبير MSDN ،

الزائد من Add التي تأخذ تم إهمال سلسلة وكائن بسبب الغموض المحتمل مع SqlParameterCollection.Add الحمل الزائد التي تأخذ String و أ SqlDbType قيمة التعداد عند تمرير عدد صحيح مع السلسلة يمكن أن يكون تفسر على أنها إما قيمة المعلمة أو المقابلة SqlDbType قيمة.يستخدم AddWithValue كلما أردت إضافة معلمة من خلال تحديد اسمها وقيمتها.

التحميل الزائد للمنشئ لـ SqlParameter class هي مجرد وسائل راحة لتعيين خصائص المثيل.إنها تختصر الكود، مع تأثير هامشي على الأداء:قد يتجاوز المنشئ أساليب الضبط ويعمل مباشرة على الأعضاء الخاصين.اذا كان هناك فرق فلن يكون كثيرا.

ماذا علي أن أفعل؟

لاحظ ما يلي (من MSDN)

لثنائي الاتجاه والإخراج المعلمات ، وقيم الإرجاع ، أنت يجب تعيين قيمة Size.هذا يكون غير مطلوب لمعلمات الإدخال ، و إذا لم يتم تعيينها بشكل صريح ، فإن القيمة هي يستنتج من الحجم الفعلي ل المعلمة المحددة عندما أ يتم تنفيذ بيان معلمات.

النوع الافتراضي هو الإدخال.ومع ذلك، إذا سمحت باستدلال الحجم على هذا النحو وقمت بإعادة تدوير كائن المعلمة في حلقة (لقد قلت أنك مهتم بالأداء)، فسيتم تعيين الحجم بواسطة القيمة الأولى وأي قيم لاحقة أطول سيتم تعيينها مقطوع.من الواضح أن هذا مهم فقط بالنسبة للقيم ذات الطول المتغير مثل السلاسل.

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

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


كان عام 2008 منذ وقت طويل

في السنوات التي تلت كتابة هذا، تغير العالم.هناك أنواع جديدة من التواريخ، وهناك أيضًا مشكلة لم تخطر على بالي حتى حدثت مشكلة حديثة مع التواريخ جعلتني أفكر في الآثار المترتبة على الاتساع.

يعد التوسيع والتضييق، بالنسبة لأولئك الذين ليسوا على دراية بالمصطلحات، من خصائص تحويلات نوع البيانات.إذا قمت بتعيين int لـ double، فلن يكون هناك فقدان للدقة لأن double هو "أوسع".من الآمن دائمًا القيام بذلك، لذا فإن التحويل يتم تلقائيًا.هذا هو السبب في أنه يمكنك تعيين int إلى مزدوج ولكن السير في الاتجاه الآخر يجب عليك إجراء عملية تحويل صريحة - double to int هو تحويل ضيق مع احتمال فقدان الدقة.

يمكن أن ينطبق هذا على السلاسل:NVARCHAR أوسع من VARCHAR، لذا يمكنك تعيين VARCHAR إلى NVARCHAR ولكن السير في الاتجاه الآخر يتطلب طاقمًا.تعمل المقارنة لأن VARCHAR يتسع ضمنيًا إلى NVARCHAR، ولكن هذا سوف يتعارض مع استخدام الفهارس!

سلاسل C# هي Unicode، لذلك سينتج AddWithValue معلمة NVARCHAR.في الطرف الآخر، يتم توسيع قيم العمود VARCHAR إلى NVARCHAR للمقارنة.هذا لا يوقف تنفيذ الاستعلام ولكنه يمنع استخدام الفهارس.هذا سيء.

ماذا يمكنك أن تفعل بهذا الشأن؟لديك حلان ممكنان.

  • اكتب المعلمة بشكل صريح.وهذا يعني عدم وجود AddWithValue أكثر
  • قم بتغيير جميع أنواع أعمدة السلسلة إلى NVARCHAR.

ربما يكون التخلص من VARCHAR هو أفضل فكرة.إنه تغيير بسيط له عواقب يمكن التنبؤ بها ويحسن قصة الترجمة الخاصة بك.ومع ذلك، قد لا يكون لديك هذا كخيار.

في هذه الأيام لا أقوم بالكثير من عمليات ADO.NET المباشرة.أصبح Linq2Sql الآن سلاحي المفضل، وقد جعلتني كتابة هذا التحديث أتساءل عن كيفية تعامله مع هذه المشكلة.لدي رغبة ملحة ومفاجئة في تطهير قواعد البيانات الخاصة بي من VARCHAR.

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

http://msdn.microsoft.com/en-us/library /dd203144.aspx

واعتدت على استخدام الخاص بك الخيار 1:

<اقتباس فقرة>   

وcmd.Parameters.Add ( "@ اسم" SqlDbType.VarChar، 20) .Value = "بوب"؛

والذي سار على ما يرام، ولكن بعد ذلك بدأت باستخدام .AddWithValue وأنها بسيطة كما يحصل. لم تسبب بها لي مشكلة بعد عدة آلاف من الاستخدامات. فتذكروا، وأنا دائما تقريبا يمر دروسي المتغيرات خاصة، ولذا فإنني لم يكن لديك ما يدعو للقلق حول نوع التحويل الضمني قدر.

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

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