هل من الممكن إرسال مجموعة من المعرفات كمعلمة ADO.NET SQL؟

StackOverflow https://stackoverflow.com/questions/114504

  •  02-07-2019
  •  | 
  •  

سؤال

على سبيل المثال.هل يمكنني كتابة شيء مثل هذا الكود:

public void InactiveCustomers(IEnumerable<Guid> customerIDs)
{
    //...
    myAdoCommand.CommandText =
        "UPDATE Customer SET Active = 0 WHERE CustomerID in (@CustomerIDs)";
    myAdoCommand.Parameters["@CustomerIDs"].Value = customerIDs;
    //...
}

الطريقة الوحيدة التي أعرفها هي الانضمام إلى IEnumerable الخاص بي ثم استخدام تسلسل السلسلة لإنشاء سلسلة SQL الخاصة بي.

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

المحلول

بشكل عام، الطريقة التي تفعل بها ذلك هي تمرير قائمة قيم مفصولة بفواصل، وضمن الإجراء المخزن، قم بتحليل القائمة وإدراجها في جدول مؤقت، والذي يمكنك بعد ذلك استخدامه للصلات.اعتبارا من أس كيو إل سيرفر 2005, هذه ممارسة قياسية للتعامل مع المعلمات التي تحتاج إلى الاحتفاظ بالمصفوفات.

إليك مقالة جيدة حول طرق مختلفة للتعامل مع هذه المشكلة:

تمرير قائمة/صفيف إلى إجراء مخزن في SQL Server

ولكن ل أس كيو إل سيرفر 2008, ، يمكننا أخيرًا تمرير متغيرات الجدول إلى إجراءات، عن طريق تعريف الجدول أولاً كنوع مخصص.

يوجد وصف جيد لهذا (والمزيد من ميزات 2008) في هذه المقالة:

مقدمة إلى ميزات برمجة T-SQL الجديدة في SQL Server 2008

نصائح أخرى

يمكنك مع SQL 2008.لم يخرج منذ فترة طويلة، لكنه متاح.

كما ذكر في تعليق, ، كتب إرلاند سومارسكوغ سلسلة من المقالات حول هذا الموضوع (مرتبط أدناه).المقالات شاملة للغاية ويمكن أن تكون بمثابة مواد مرجعية.على الرغم من أنها خاصة بـ SQL Server (T-SQL)، إلا أن بعض التقنيات المذكورة قد تعمل أيضًا مع RDBMS أخرى (مثل استخدام XML نوع البيانات):

يمكنك استخدام نوع معلمة XML:

CREATE PROCEDURE SelectByIdList(@productIds xml) AS

DECLARE @Products TABLE (ID int) 

INSERT INTO @Products (ID) SELECT ParamValues.ID.value('.','VARCHAR(20)')
FROM @productIds.nodes('/Products/id') as ParamValues(ID) 

SELECT * FROM 
    Products
INNER JOIN 
    @Products p
ON    Products.ProductID = p.ID

http://weblogs.asp.net/jgalloway/archive/2007/02/16/passing-lists-to-sql-server-2005-with-xml-parameters.aspx

لا.المعلمات تشبه قيم SQL في الطاعة النموذج العادي الأول, في الأساس، لا يمكن أن يكون هناك سوى واحد...

كما تعلم، فإن إنشاء سلاسل SQL يعد عملاً محفوفًا بالمخاطر:تترك نفسك مفتوحًا أمام هجوم حقن SQL.طالما أنك تتعامل مع معرّفات GUID حقيقية، فيجب أن تكون على ما يرام، ولكن بخلاف ذلك عليك التأكد من تنظيف مدخلاتك.

لا يمكنك تمرير قائمة كمعلمة SQL واحدة.يمكنك استخدام string.Join(',') للمعرفات الفريدة العمومية (GUIDs) مثل "0000-0000-0000-0000، 1111-1111-1111-1111" ولكن هذا سيكون مرتفعًا على قاعدة البيانات ودون المستوى الأمثل حقًا.ويجب عليك تمرير السلسلة بأكملها كبيان ديناميكي متسلسل واحد، ولا يمكنك إضافتها كمعلمة.

سؤال:

من أين تحصل على قائمة المعرفات التي تمثل العملاء غير النشطين؟

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

    Create procedure usp_DeactivateCustomers 
    @inactive varchar(50) /*or whatever values are required to identify inactive customers*/
    AS    
    UPDATE Customer SET c.Active = 0 
    FROM Customer c JOIN tableB b ON c.CustomerID = b.CustomerID 
    WHERE b.someField = @inactive

ونسميها كإجراء مخزن:

public void InactiveCustomers(string inactive)
{
    //...
    myAdoCommand.CommandText =
        "usp_DeactivateCustomers";
    myAdoCommand.Parameters["@inactive"].Value = inactive;
    //...
}

إذا كانت قائمة المعرفات الفريدة العمومية (GUID) موجودة في قاعدة بيانات، فلماذا أحتاج إلى:اعثر عليهم؛وضعها في قائمة عامة؛قم بفك القائمة إلى متغير CSV/XML/Table، فقط لإعادتها إلى قاعدة البيانات مرة أخرى ؟؟؟؟؟؟إنهم هناك بالفعل!هل فاتني شيء؟

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