هذه المقالة متعلقة بقواعد بيانات Microsoft
SQL Server وتناقش النقاط التالية:
-
تحويل
دالة C# إلى دالة SQL
Server واستخدامها ضمن الاستعلامات المنفذة على
قاعدة بيانات SQL Server
المتطلبات السابقة لقراءة هذه المقالة:
-
إلمام
بأساسيات قواعد بيانات Microsoft SQL Server
-
إلمام
بأساسيات لغة البرمجة C#
وبيئة التطوير المتكاملة Visual Studio
تعتبر
لغة Transact-SQL هي الخيار البديهي لإنشاء دوال SQL Server معرفة بواسطة المستخدم، ولكنها ليست الخيار
الوحيد لذلك، يمكنك استخدام لغة برمجية من لغات .NET كلغة C# على سبيل المثال لإنشاء دالة SQL Server، يُعرف هذا النوع من الدوال باسم CLR SQL Server User-Defined
Functions
، اعتقد أن التسمية واضحة باستثناء الكلمة الأولى فيها وهي CLR ، ما هو الـ CLR؟ وما علاقته بموضوعنا و بلغة C# ؟ حسناً، في الحقيقة هذه المقالة ليست
للحديث عن إطار عمل دوت نت ومكوناته، ولكن باختصار، الـ CLR هو أحد المكونات الرئيسية الهامة في إطار
عمل دوت نت وهو المسؤول عن القيام بالترجمة الفورية JIT Compilation من اللغة الوسيطة IL التي تكتب بها مخرجات مترجمات لغات .NET مثل مترجم C# إلى الشفرة المنخفضة أو ما يعرف بالـ Native code ، لذلك يصح مجازاً أن نطلق على لغات .NET أنها لغات CLR ، وبذلك اعتقد أن جزء CLR في التسمية السابقة قد أصبح واضحاً بالنسبة
لك!
إذا
كنت قد قرأت
مقالتي التي تحدثت فيها عن دالة soundex فلابد
أنك قد وجدت في الجزء الأخير من المقالة تمثيل لخوارزمية soundex الداعمة للغة العربية باستخدام لغة C# ، وقد كانت الدالة كالآتي:
public static string SoundexAr(string word)
{
int length = 4;
// Value to return
string value = "";
try
{
switch (word[0])
{
case 'ا':
case 'أ':
case 'إ':
case 'آ':
{
word =
word.Substring(1, word.Length - 1);
}
break;
}
// Size of the word to process
int size = word.Length;
// Make sure the word is at least two
characters in length
if (size > 1)
{
// Convert the word to
character array for faster processing
char[] chars = word.ToCharArray();
// Buffer to build up
with character codes
StringBuilder buffer = new StringBuilder();
buffer.Length = 0;
// The current and
previous character codes
int prevCode = 0;
int currCode = 0;
// Ignore first
character and replace it with fixed value
buffer.Append('x');
// Loop through all
the characters and convert them to the proper character code
for (int i = 1; i < size;
i++)
{
switch (chars[i])
{
case 'ا':
case 'أ':
case 'إ':
case 'آ':
case 'ح':
case 'خ':
case 'ه':
case 'ع':
case 'غ':
case 'ش':
case 'و':
case 'ي':
currCode = 0;
break;
case 'ف':
case 'ب':
currCode = 1;
break;
case 'ج':
case 'ز':
case 'س':
case 'ص':
case 'ظ':
case 'ق':
case 'ك':
currCode = 2;
break;
case 'ت':
case 'ث':
case 'د':
case 'ذ':
case 'ض':
case 'ط':
currCode = 3;
break;
case 'ل':
currCode = 4;
break;
case 'م':
case 'ن':
currCode = 5;
break;
case 'ر':
currCode = 6;
break;
}
// Check to see if the
current code is the same as the last one
if (currCode !=
prevCode)
{
// Check to see if the
current code is 0 (a vowel); do not process vowels
if (currCode != 0)
buffer.Append(currCode);
}
// Set the new
previous character code
prevCode = currCode;
// If the buffer size
meets the length limit, then exit the loop
if (buffer.Length ==
length)
break;
}
// Pad the buffer, if
required
size = buffer.Length;
if (size < length)
buffer.Append('0', (length - size));
// Set the value to
return
value = buffer.ToString();
}
// Return the value
return value;
}
catch
{
return "0000";
}
}
سنقوم
بتحويل دالة C# السابقة إلى دالة SQL Server ، لذلك يرجى اتباع الخطوات التالية:
(ملاحظة: لقد تم اختبار الخطوات التالية
على Visual Studio Ultimate 2013 Update 4 و SQL Server Express 2008 R2 ، قد تختلف الخطوات اعتماداً على نوع الإصدارات التي تستخدمها)
1.
تأكد أولاً من تحديث مكونات فيجوال
ستوديو، تحديداً تحديث Microsoft
SQL Server for Database Tooling لكي لا تواجه مشاكل أثناء بناء ونشر المشروع. للقيام بذلك: من Visual Studio اختر القائمة Tools ثم الخيار Extensions and Updates ، ثم اضغط على Update الخاص بالتحديث المذكور بالأعلى، ثم تابع
الخطوات المعروضة على شاشتك لإتمام التحديث.
2. من
نافذة SQL Server
Object Explorer ، انقر على قاعدة
البيانات التي تريدها بالزر الأيمن واختر إنشاء مشروع قاعدة بيانات جديد.
3. تظهر
النافذة التالية، اضغط على زر start:
4.
الآن قم باتباع الخطوات الموضحة في
الصور التالية، النتيجة ستكون كما في الصورة الأخيرة:
5. في
الصورة الأخيرة ستجد تعريف الدالة SoundexAr التي تستقبل المدخل من نوع string وسترجع كائن من نوع SqlString والذي سيستقبل مشيده القيمة النصية التي
سيتم سيتم إرجاعها أثناء استدعاء الدالة SoundexAr . في جسم الدالة، قم باستبدال الكود الافتراضي التي تمت إضافته
أثناء إنشاء الملف بجسم دالة C# السابقة مع مراعاة تعديل جمل الإرجاع return statements لكي ترجع قيم متوافقة مع النوع المصرح به في
تعريف الدالة، سيكون تعريف وجسم الدالة كما يلي:
public static SqlString SoundexAr(string word)
{
int length = 4;
// Value to return
string value = "";
try
{
switch (word[0])
{
case 'ا':
case 'أ':
case 'إ':
case 'آ':
{
word =
word.Substring(1, word.Length - 1);
}
break;
}
// Size of the word to process
int size = word.Length;
// Make sure the word is at least two
characters in length
if (size > 1)
{
// Convert the word to character array
for faster processing
char[] chars = word.ToCharArray();
// Buffer to build up with character
codes
System.Text.StringBuilder buffer = new System.Text.StringBuilder();
buffer.Length = 0;
// The current and previous character
codes
int prevCode = 0;
int currCode = 0;
// Ignore first character and replace
it with fixed value
buffer.Append('x');
// Loop through all the characters and
convert them to the proper character code
for (int i = 1; i < size; i++)
{
switch (chars[i])
{
case 'ا':
case 'أ':
case 'إ':
case 'آ':
case 'ح':
case 'خ':
case 'ه':
case 'ع':
case 'غ':
case 'ش':
case 'و':
case 'ي':
currCode = 0;
break;
case 'ف':
case 'ب':
currCode = 1;
break;
case 'ج':
case 'ز':
case 'س':
case 'ص':
case 'ظ':
case 'ق':
case 'ك':
currCode = 2;
break;
case 'ت':
case 'ث':
case 'د':
case 'ذ':
case 'ض':
case 'ط':
currCode = 3;
break;
case 'ل':
currCode = 4;
break;
case 'م':
case 'ن':
currCode = 5;
break;
case 'ر':
currCode = 6;
break;
}
// Check to see if the
current code is the same as the last one
if (currCode !=
prevCode)
{
// Check to see if the
current code is 0 (a vowel); do not process vowels
if (currCode != 0)
buffer.Append(currCode);
}
// Set the new
previous character code
prevCode = currCode;
// If the buffer size
meets the length limit, then exit the loop
if (buffer.Length == length)
break;
}
// Pad the buffer, if required
size = buffer.Length;
if (size < length)
buffer.Append('0', (length - size));
// Set the value to return
value = buffer.ToString();
}
// Return the value
return new SqlString(value);
}
catch
{
return new SqlString("0000");
}
}
6.
الآن وقبل بناء ونشر الحل، قم التحقق
من تكامل الـ
CLR
الخاص بنسخة قواعد البيانات التي تستخدمها واجعل مشروعك متوافق مع إطار عمل دوت نت
المتكامل مع نسخة قواعد البيانات التي تستخدمها، قم بتنفيذ الاستعلام التالي على
قاعدة البيانات لمعرفة رقم تكامل الـ CLR:
SELECT * FROM sys.dm_clr_properties;
7. توجه
إلى خصائص المشروع، وقم بتعديل إطار العمل الهدف ليتوافق مع النتيجة التي أظهرها
الاستعلام السابق:
8. قم
ببناء ونشر الحل، يمكنك عمل ذلك بخطوة واحدة سريعة، الضغط على زر Start والذي يظهر في شريط الأدوات بجابنه سهم
أخضر، مع تحديد تهيئة البناء والنشر لتكون Release كما هو موضح في الصورة:
9. أخيرا
قم بإضافة المرجع – ملف .dll
– التي تم إنتاجه بواسطة الخطوة السابقة إلى قاعدة البيانات، ومن
ثم قم بإنشاء دالة SQL
Server
تستخدم المرجع السابق، يمكنك عمل ذلك عبر تنفيذ الاستعلام التالي على قاعدة
البيانات مع تغيير ما يلزم في الكود – مثل مسار المرجع - :
--
Install Assembly
CREATE ASSEMBLY MyHotelAssembly FROM
'C:\MyHotelDatabaseProject1.dll'
GO
-- Create
SoundexAr Function
CREATE FUNCTION [dbo].[SoundexAr](@word nvarchar(max))
RETURNS nvarchar(4)
WITH EXECUTE AS CALLER
AS
EXTERNAL NAME
MyHotelAssembly.UserDefinedFunctions.SoundexAr;
GO
10.
الآن يمكنك استخدام الدالة السابقة ضمن
استعلامات SQL
Server ، قم بتجربة الاستعلام التالي لترى النتيجة:
SELECT dbo.SoundexAr(N'احمد'), dbo.SoundexAr(N'أحمد'), dbo.SoundexAr(N'أحميد'), dbo.SoundexAr(N'احمدد');
تهانينا!
لقد قمت بتعريف دالة مكتوبة بلغة C# لكي تكون دالة SQL Server