ייצור אוטומטי של סקריפטי התקנה והסרה של SQL CLR Functions / Stored Procedures

17 בNovember 2015

תגיות: , ,
אין תגובות

לפני כמה ימים פרסמתי פוסט על משהו קטן שעבדתי עליו בין תרגיל אינפי לתרגיל לינארית, שכולל למעשה אוסף של functions ו- stored procedures המאפשרים עבודה מול Redis מ- SQL Server, כאשר מרבית הפרוייקט זה סה”כ תפירה בין קוד C# קיים לעבודה מול Redis ל- SQL Server – שמתבצעת באמצעות SQL CLR, פיצ’ר חביב (למרות שהיה יכול להיות טוב משמעותית) שמאפשר לשלב ולכתוב רכיבים שונים בדטאבייס (functions, stored procedures וכו’) ב- C#.

הדרישה שהייתה לי לצרכי פיתוח הייתה פשוטה – שבסוף כל build יהיה לי קובץ install.sql שכשאני מריץ אותו הוא מכיל את כל ה- CREATE statements של ה- CLR functions / procedures שלי, ו- uninstall.sql שכולל את ה- DROP statements הרלוונטיים. הדבר העיקרי ממנו רציתי להימנע זה התענוג (המפוקפק) בלהכין create statements לכל פונקציה בנפרד, ואז כל פעם שמשנים במהלך הפיתוח את הפרמטרים לעדכן גם בקוד C# וגם בסקריפט ה-SQL-י ולייצר למעשה שכפול מיותר של הגדרות.

הפיתרון הראשון שאליו הסתכלתי היה לממש הכל באמצעות SSDT. למי שלא מכיר, SSDT (SQL Server Data Tools), הוא פרוייקט של מיקרוסופט של תוסף ל- Visual Studio שמאפשר לייצג דטאבייס בתור פרוייקט ב-Visual Studioהכולל item-ים שונים: טבלאות, views, stored procedures, טריגרים, SQL CLR Functions – בקיצור, פחות או יותר כל מה שרוצים. SSDT תומך בתרחיש deployment באמצעות dacpac או באמצעות יצירת סקריפטי מיגרציה SQL-יים.
בעבר עשיתי מספר ניסיונות ב-SSDT לשימושים היותר קונבנציונליים שלו (ניהול סכימה של DB בתור פרוייקט) ופסלתי אותו כי הוא לא היה נוח (גם מבחינת תרחיש העבודה, וגם לשימוש באופן כללי). החלטתי שזה יכול להיות ניסיון טוב להשתמש בו.

צריך להבין שהתרחיש המקורי אליו מיועד SSDT שונה מהתרחיש שהיה לי במקרה הספיציפי הזה. התרחיש המקורי הוא כאמור שימוש לניהול סכימה של DB. בתרחיש המסויים שלי, אני רוצה לנהל פרוייקט שמייצג משהו שאנשים יכולים “להתקין” לתוך ה-DB שלהם. ובכל זאת, חשבתי שבזכות היכולת שלו לעקוב אחרי שינויי סכימאות, והעובדה שניתן להוסיף אליו CLR functions וכו’ הוא יתאים. די מהר התבדיתי – העבודה מולו מאד לא נוחה. כשאומרים לו לייצר סקריפטים (ולא לעבוד עם DAC), אז כל ייצור סקריפט לפרוייקט קטנטן לוקח מס’ דקות. אמנם לא רב, אבל הרבה יותר מהמס’ שניות שנראה לי סביר ונוח לצרכי עבודה שוטפת. בנוסף, התברר לי שהוא לא תומך בפונקציונאליות בסיסית מאד שרציתי – למשל קביעת default values שונים ל- CLR functions (ב-connect זה עדיין בקשה פתוחה).
מכיוון שהוא לא היה כיפי לשימוש, וגם לא נתן כל מה שרציתי – החלטתי שהוא לא מתאים לצורך הזה.

אז מכיוון שלמרות הכל לא רציתי לכתוב בעצמי באמצעות copy-paste את ה-SQL-ים של ההתקנה וההסרה, החלטתי לפתח משהו פשוט שייצר אותם עבורי עם Reflection. בסופו של דבר, יצרתי פרוייקט שמכיל אוסף של attributes שמתארים את כל ה- metadata הנוסף שצריך עבור ייצור הסקריפטים הללו, מעבר לזה שקיים כבר ב SqlFunctionAttribute וב- SqlProcedureAttribute.  כל מתודה שיצרתי שאמורה להתווסף כ- CLR function/procedure כוללת את ה- attributes הרלוונטיים.
בנוסף, יצרתי console application קטן שמייצר ע”ס ה-attributes האלה CREATE / DROP statements ומשלב אותם בקובץ טקסט שמכיל טמפלייט רלוונטי (שכולל אפשרות גם לעשות include לקבצי SQL אחרים). יש קובץ טמפלייט גם להתקנה וגם להסרה, שעל פיהם מג’ונרט הסקריפט התקנה והסרה הסופי, באמצעות post build events.

מכיוון שרוב הפרוייקט שלי מבוסס על CLR funcitons ו- CLR procedures, זה מה שהיה חשוב לי לפתור. את הקוד T-SQL שכן קיים, אני משלב בקובץ template באמצעות תמיכה ב- include (כלומר, אין משהו חכם שמתמודד עם stored procedures / functions שכתובים ב- T-SQL).  כמובן שפונקציונאליות אחרת שאני לא משתמש בה בכלל (כמו CLR Triggers) בכלל  לא כלולה בפרוייקט הזה.

אם אתם כותבים משהו שמבוסס על SQL CLR (ובכנות, נראה לי שזה משהו די נדיר), יכול להיות שזה יהיה רלוונטי עבורכם (למרות שאני מקווה ש- SSDT פשוט ישתפר, כי הוא הפיתרון הטבעי לזה). הקוד הרלוונטי זמין ב- GitHub.

הוסף תגובה
facebook linkedin twitter email

Leave a Reply

Your email address will not be published. Required fields are marked *