[.net] مقارنة سلسلة غير حساسة لحالة الأحرف في LINQ-to-SQL


Answers

أنا استخدم System.Data.Linq.SqlClient.SqlMethods.Like(row.Name, "test") في الاستعلام الخاص بي.

يقوم هذا بإجراء مقارنة غير متحسسة لحالة الأحرف.

Question

لقد قرأت أنه من غير الحكمة استخدام ToUpper و ToLower لإجراء مقارنات غير حساسة لحالة الأحرف ، ولكن لا أرى بديلاً عندما يتعلق الأمر بـ LINQ-to-SQL. يتم تجاهل وسيط ignoreCase و CompareOptions String.Compare بواسطة LINQ-to-SQL (إذا كنت تستخدم قاعدة بيانات حساسة لحالة الأحرف ، فستحصل على مقارنة حساسة لحالة الأحرف حتى إذا طلبت إجراء مقارنة غير حساسة لحالة الأحرف). هل ToLower أو ToUpper أفضل خيار هنا؟ هل أفضل من الآخر؟ ظننت أنني قرأت في مكان ما أن ToUpper كان أفضل ، لكنني لا أعرف ما إذا كان ذلك ينطبق هنا. (أنا أفعل الكثير من مراجعات الكود والجميع يستخدم ToLower.)

Dim s = From row In context.Table Where String.Compare(row.Name, "test", StringComparison.InvariantCultureIgnoreCase) = 0

هذا يترجم إلى استعلام SQL يقارن ببساطة row.Name مع "اختبار" ولن يقوم بإرجاع "اختبار" و "اختبار" على قاعدة بيانات لحالة الأحرف.




إذا قمت بتمرير سلسلة غير حساسة لحالة الأحرف إلى LINQ-to-SQL ، فسيتم تمريرها إلى SQL بدون تغيير وستحدث المقارنة في قاعدة البيانات. إذا كنت تريد إجراء مقارنات سلسلة غير حساسة لحالة الأحرف في قاعدة البيانات ، كل ما عليك القيام به هو إنشاء تعبير lambda الذي يقوم بإجراء المقارنة وسيقوم موفر LINQ-to-SQL بترجمة هذا التعبير إلى استعلام SQL مع احتفاظ السلسلة الخاصة بك سليمة.

على سبيل المثال هذا الاستعلام LINQ:

from user in Users
where user.Email == "foo@bar.com"
select user

يتم ترجمتها إلى SQL التالي بواسطة موفر LINQ إلى SQL:

SELECT [t0].[Email]
FROM [User] AS [t0]
WHERE [t0].[Email] = @p0
-- note that "@p0" is defined as nvarchar(11)
-- and is passed my value of "foo@bar.com"

كما ترى ، ستتم مقارنة معلمة السلسلة في SQL ، مما يعني أن الأشياء يجب أن تعمل بالطريقة التي تتوقعها بها.




تذكر أنه يوجد فرق بين ما إذا كان الاستعلام يعمل وما إذا كان يعمل بكفاءة ! يتم تحويل عبارة LINQ إلى T-SQL عندما يكون هدف البيان هو SQL Server ، لذلك تحتاج إلى التفكير في T-SQL التي سيتم إنتاجها.

استخدام String.Equals على الأرجح (أحزر) أحضر كافة الصفوف من SQL Server ثم قم بإجراء المقارنة في .NET ، لأنه تعبير .NET لا يمكن ترجمته إلى T-SQL.

بمعنى آخر ، يؤدي استخدام التعبير إلى زيادة الوصول إلى البيانات وإزالة قدرتك على استخدام الفهارس. ستعمل على طاولات صغيرة ولن تلاحظ الفرق. على طاولة كبيرة يمكن أن يؤدي بشكل سيء للغاية.

هذه واحدة من المشاكل الموجودة مع LINQ ؛ لم يعد الناس يفكرون في كيفية تنفيذ البيانات التي يكتبونها.

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




where row.name.StartsWith(q, true, System.Globalization.CultureInfo.CurrentCulture)



Links