May 2007 - Posts
לאחר שיטוט קצר באינטרנט וחיפוש אחר כלים לפיתוח, מצאתי כלי שנקרא QueryCommander, עורך SQL מתקדם עם Intellisense בקוד פתוח.
העורך מתאים לעבודה עם מסדי נתונים שונים בינהם SQL Server 2000/2005 וגם Oracle. הוא כמובן מריץ את הקוד על שרת ה - SQL (ממש כמו QueryAnalyzer), עם צביעת קוד, סביבת עבודה כמו של Visual Studio (ממש נוחה), Server Explorer, Code Snippets ועוד הרבה פיצ'רים.
יש לה כמה חסרונות, למשל לא ניתן לשנות את הצבעים (של הקוד), והיא לא תמיד יודעת להצביע על המיקום של השגיאה בקוד ה - SQL (מספר השורה לא נכון, ולעתים גם השגיאה). (ולכן לעיתים אני עוד משתמש ב - Query Analyzer הישן והטוב), אבל מעבר לכך זו אחלה תוכנה, אני ממליץ בחום.
הנה ScreenShot נחמד מ - SourceForge:

דף הבית של התוכנה ב - SourceForge
באפליקציות גדולות בעלי מסד נתונים מכובד ומורכב, אנו עלולים למצוא עצמנו מנסים לדלות מידע מהמסד בדרכים שונות ומשונות. שאילתות מסובכות שמחזירות מידע ממספר טבלאות עם תנאים ופונקציות שבאו מעולמות אחרים כנראה.
אחד הפתרונות לפישוט המסד והשאילתות הוא להשתמש ב - Views. בפוסט זה אתייחס למילה CASE והשימוש בה בשאילתות וב - Views.
נתון המסד הבא:

- המסד מכיל סרטים, קטגוריות ומשתמשים.
- כל סרט משויך לקטגוריה. (CategoryID)
- כל משתמש יכול לבחור מספר קטגוריות של סרטים שהוא אוהב (טבלת UsersLikesCategories).
- לכל סרט יש תאריך שבו הוא יוצא לאקרנים (StartDate), והתאריך האחרון שבו הוא משודר בקולנוע (EndDate). תאריך ה - EndDate הוא Nullble, מכיוון שלא תמיד ידוע מתי הסרט יורד מהמסך.
הבעיה:
עלינו להציג למשתמש את כל הסרטים בקטגוריות שהוא אוהב, כשליד כל סרט שיורד מהמסך בחודש הגרגוריאני הזה או הבא - תוצג הערה או סימון. במידה וה - EndDate הוא Null - לא תוצג הערה.
אם יש לכם ניסיון ב - SQL, אני מניח שאתם כבר יודעים איך השאילתה הזו אמורה להראות. צירוף טבלאות עם תנאים מוזרים. אולי בכלל תחליטו לטפל בבעית ההערה באפליקציה ולא במסד.
פתרון לבעית התאריכים
ניצור View חדש בשם vwMovies. באמצעות CASE ניצור בקלות שדה בוליאני (BIT) שיחזיר True במידה ויש להציג את ההערה, לשדה זה נקרא Notice.
המבנה של משפט Case הוא כדלהלן:
1 2 3 4 |
CASE WHEN condition THEN trueresult [ELSE elseresult] END |
נתחיל מלבדוק אם הערך EndDate הוא Null או לא. בשלב זה השדה יחזיר 1 אם EndDate הוא לא Null ו - 0 אם הוא Null, הנה הקוד, לאחר מכן ההסבר:
1 2 3 4 5 6 7 8 9 10 |
CREATE VIEW vwMovies AS SELECT MovieID, CategoryID, Title, Description, StartDate, EndDate, CONVERT(BIT, (CASE WHEN (EndDate IS NULL) THEN 0 ELSE 1 END) ) AS Notice FROM Movies GO |
הסבר לקוד, ואני אתחיל מהקטע החשוב - שורות 5 ו - 6:
שורה 5 מתחילה במילה CASE, ולאחריה WHEN - שבודק את התנאי EndDate IS NULL. המשפט CASE מתחיל בשורה חמש וממשיך בשורה 6: THEN - יקרה במידה והתנאי שב - WHEN מתקיים. ELSE, יקרה במידה והתנאי לא התקיים. במקרה שלנו אם EndDate הוא NULL, יוחזר 0 (אל תתריע), אחרת יוחזר 1 (יש תאריך סיום).
והסבר לשאר השורות:
-
יצירת View חדש בשם vwMovies.
-
משפט Select
-
רשימת השדות שיש לבחור
-
הפונקציה CONVERT, שמקבלת טיפוס וערך, ומבצעת הסבה. במקרה שלנו, הערך הוא מה שיוחזר ממשפט ה - CASE שיצרנו (0 או 1), והטיפוס יהיה BIT.
-
בשורה זו אנחנו נותנים לשדה את שמו - Notice, בשורה אחת זה נראה כך:
CONVERT(BIT, [Case Clause]) AS Notice
-
בשורות 8-9 אנחנו בוחרים את הטבלה ממנה נשלוף את הנתונים.
עכשיו נותר לטפל בתאריך במידה והוא קיים. לצורך כך, נשתמש בפונקציה DatePart. הפונקציה מקבלת את החלק של התאריך שאנחנו רוצים להחזיר, ואת התאריך, ומחזירה INT. דוגמה פשוטה לשימוש בה (בהנחה שהיום 29 למאי, שעה 21:10):
1 2 |
SELECT DatePart(month, GetDate()); -- Returns 5 SELECT DatePart(hour, GetDate()); -- Returns 21 |
במקרה שלנו צריך לבדוק את החודש והשנה, לכן התנאי שלנו יהיה:
1 2 3 4 5 6 |
DatePart(year, EndDate) = DatePart(year, GetDate()) AND ( DatePart(month, EndDate) = DatePart(month, GetDate()) OR DatePart(month, EndDate) = (DatePart(month, GetDate()) + 1) ) |
יש עוד מיליון דרכים לבצע את הבדיקה הזו, אבל לצורך העניין התנאי הוא:
אם השנה ב - EndDate זהה לשנה הנוכחית (GetDate) וגם (החודש ב - End זהה לחודש הנוכחי או לחודש הבא)
את כל זה נעטוף ב - CASE שיחזיר 1 אם התנאי מתבצע (כלומר יש להתריע), אחרת יחזיר 0. ונשים אותו בתוך ה - CASE הקודם שבנינו, במידה וה - EndPart הוא לא NULL.
מה שיצא זה:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
CREATE VIEW vwMovies AS SELECT MovieID, CategoryID, Title, Description, StartDate, EndDate, CONVERT(BIT, (CASE WHEN (EndDate IS NULL) THEN 0 ELSE
(CASE WHEN ( DatePart(year, EndDate) = DatePart(year, GetDate()) AND ( DatePart(month, EndDate) = DatePart(month, GetDate()) OR DatePart(month, EndDate) = (DatePart(month, GetDate()) + 1) ) ) THEN 1 ELSE 0 END) END) ) AS Notice FROM Movies GO |
יש כמובן עוד דרכים לפשט גם את זה. אבל לא נעסוק בזה עכשיו. מה שקיבלנו זה View שמחזיר את רשימת הסרטים בתוספת השדה Notice שיראה לנו האם הסרט יורד מהמסכים בקרוב.
ה - View הזו כמובן היא מבחינתו טבלה שאפשר לשלב ב - SP's שלנו ועוד, ולשנות גם את הכללים לסרט שיש להתריע עליו בקלות יחסית. מכאן הדרך לשאר השאילתה היא הרבה יותר פשוטה. אני אשאיר לכם לעשות את שיעורי הבית ;)
עד כאן. נתראה בפוסט הבא...
מבוא
בסדרת מדריכים זו - אסביר איך ליצור Custom Conotrol (להלן "פקד") לדפי ה - ASP.NET. הפקדים ב - ASP.NET הם כלי מאוד חזק. היתרונות הם רבים וכאן אכתוב רק מעט מהם:
- פקדים עוזרים לשמור על קוד נקי ולהפריד את העיצוב (דפי ה - ASPX) מהקוד (CodeBehind).
- פקדים מתקמפלים וניתן להשתמש בהם שוב ושוב בדפים ופרוייקטים שונים (ואף לשים אותם ב - GAC)
- הפקדים משמשים כ - "קופסה שחורה", שבאה לספק לנו התנהגות כלשהי, וניתן לנהל אותם בקלות באמצעות מתודות, אירועים ו - Propeties שהם חושפים (אלו מופיעים גם ב - Intellisense).
- הפקדים יכולים לכלול בתוכם משאבים שנחוצים להפעלתם כגון קבצי JavaScript, קבצי CSS וכיו"ב - ומונעים מאיתנו להתעסק עם הוספת קבצים אלו בכל דף.
- פקדים יכולים לשלב בתוכם קוד צד שרת שמשולב עם קוד צד לקוח, לנהל ולהעבי מידע ב - ViewState, לעבוד עם פקדים אחרים ועוד ועוד.
ההתחלה
על מנת שנוכל ליצור פקד בקלות, ניצור אתר חדש ב - Visual Studio ( > ) ונבחר ב - Empty Web Site.
בתוך האתר ניצור תיקיית ASP ששמה App_Code, ונוסיף class חדש, שהוא יהיה הפקד שלנו. נקרא לו HelloWorldControl.cs, בקוד שנוצר מה - Visual Studio נוסיף הורשה - הפקד שלנו צריך לרשת מ - System.Web.UI.Control. הקוד של הפקד עכשיו צריך להראות כך (אחרי שהעפנו namespaces מיותרים):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
using System; using System.Web; using System.Web.UI;
/// <summary> /// Summary description for HelloWorldControl /// </summary> public class HelloWorldControl : System.Web.UI.Control { public HelloWorldControl() { // // TODO: Add constructor logic here // } } |
עכשיו יש לנו את הקוד הבסיסי לפקד. ולו נוסיף (או נדרוס, זכרו - מי שמשתמש ב - override מחבל בחיי אדם) את הפונקציה שמרנדרת את הפקד (הלא היא Render):
protected override void Render(HtmlTextWriter writer)
{
writer.Write("Hello World!");
}
כאן אני מניח שאתם מבינים מה יקרה עכשיו אם נוסיף את הפקד לדף כלשהו. אבל בכל זאת, אסביר בקצרה מה עשינו כאן:
- יצרנו class חדש בשם HelloWorldControl, שזה יהיה שמו של הפקד.
- ירשנו מ - System.Web.UI.Control שהיא מחלקת האם (או האב) של כל הפקדים ב - ASP.NET.
- דרסנו את המתודה Render - זוהי מתודה המקבלת אובייקט מסוג HtmlTextWriter, שעליו נסביר בקצרה לאחר שתסיימו לקרוא את שלושת הסעיפים הללו. מתודה זו יוצרת את הקוד שיפלוט הפקד לדף ה - ASPX.
האובייקט HtmlTextWriter נועד על מנת לעבוד וליצור קוד Html בקלות. המתודה בה השתמשנו היא Write, מתודה זו פשוט כותבת את הטקסט שהיא מקבלת. אם נרצה ליצור תג Html כלשהו, נוכל להשתמש במתודות נוספות, כגון RenderBeginTag ו - RenderEndTag:
- RendrBeginTag - מקבלת String או HtmlTextWriterTag שהוא enumeration שמונה תגיות שונות של Html, ויוצרת תגית פתיחה ב - Html.
- RenderEndTag - סוגרת את התגית האחרונה שנפתחה.
אם נרצה שהפקד יציג את צמד המלים "Hello World" בכותרת מסוג Heading1, נוכל לבצע זאת כך:
protected override void Render(HtmlTextWriter writer)
{
writer.RenderBeginTag(HtmlTextWriterTag.H1);
writer.Write("Hello World!");
writer.RenderEndTag();
}
עכשיו אחרי שיצרנו את הקונטרול הפשוט שנקרא HelloWorldControl, נשים אותו תחת ה - namespace שנקרא MyControls ונוסיף אותו לדף ASPX. לצורך כך ניצור דף ASP.NET חדש בפרוייקט שלנו ונקרא לו Default.aspx.
בראש הדף (אחרי הגדרת ה - @Page) "נרשום" את הפקד שלנו על מנת שה - ASP.NET יזהה אותו, באמצעות Register:
<%@ Register Namespace="MyControls" TagPrefix="hwc" %>
והסבר:
- Register משמש על מנת "ליידע" את הדף על פקדים חדשים.
- Namespace - ה - namespace תחתיו יושב ה - Control שלנו.
- TagPrefix - ה - Prefix של התגים (לדוגמה ה - Prefix של TextBox הוא asp, ולכן השם של התג הוא asp:TextBox). במקרה הזה בחרתי ב - hwc, שזה ראשי תיבות של Hello World Control.
- ומה עם שם התג? השם יהיה השם של ה - class.
במקרה הזה, הפקד שלנו יושב בתוך תיקיית ה - App_Code (משמע באותו פרוייקט), בד"כ רצוי ליצור את הפקדים בפרוייקט נפרד, על מנת שיהיה לנו DLL שנוכל להוסיף לכל פרוייקט. במקרה זה נוסיף גם את המאפיין Assembly - וערכו יהיה השם של ה - Assembly של הפרוייקט.
עכשיו נעשה Build לאתר (בקיצור: Ctrl + Shift + B), ולאחר שהוא התקמפל בהצלחה, ניגש לדף ה - ASPX שלנו וננסה להוסיף את הפקד החדש שיצרנו. הנה תמונה:

אפשר לראות כי הפקד מופיע ב - Intellisense של ה - VS. עכשיו נוסיף אותו, נקמפל ונריץ. הקוד:
<hwc:HelloWorldControl runat="server"/>
נריץ את האתר - ונוכל לראות את התוצאה: H1 ובתוכו המלים Hello World.
סוף דבר לחלק א'
בזה סיימתם את השלב הראשון בבניית פקד פשוט ביותר והבנה של יצירת פקד חדש. בחלקים הבאים אסביר איך ליצור לפקד מאפיינים, אירועים, משאבים (כגון קבצי JavaScript) ועוד.
יצירת Custom Controls - חלק ב' - Properties & Exceptions
בגדול אני לא תומך נלהב בכלל של Ajax ועיבוד מידע מבלי לעבור דפים, למרות זאת, יש כמה מקרים בהם זה יכול להיות שימושי, ואף עדיף במקרים ספיציפיים. Microsoft הוציאה Framework שנקרא AJAX (שהיה בעבר Atlas), ואיתו מספר Controls נחמדים.
בתור חובב מושבע של טכנולוגית ה - AJAX (או שלא), מה שכן התלהבתי ממנו - הוא ה - Ajax Control Toolkit שמתווספים ל - AJAX, יש שם כמה פקדים ממש שימושיים - כמו Calendar שרץ בצד לקוח, Rating (ממש כמו הדירוג של הפוסט פה ב - CommunityServer), טאבים, ModalPopup - ועוד.
נכון שלא כולם מתקשרים ל - Ajax - ולהתקשרות עם השרת מבלי לבקש דף חדש - אבל הפקדים האלו עושים עבודה טובה, וחוסכים התעסקות עם JavaScript ומשאירים את הקוד שלנו מסודר ונקי.
היופי ב - AJAX ובפקדים האלו הם שמעבר לכך שהם קלים לשימוש - הם גם עובדים בצורה טובה על שאר דפדפנים. וכל זה בחינם!
אבל, (אבל?! מה פתאום אבל?!?!)
כן כן, אבל - ישנם שני חסרונות רציניים כשעובדים עם הפקדים האלו (ואני מדבר על ה - Control Toolkit):
-
התקנה
צריך להתקין את ה - AJAX Framework על השרת (על ה - Production Server). כן, שמעתם טוב (או קראתם אם ממש במקרה אתם רואים טוב ולא משתמשים בקורא מסך). צריך להתקין על השרת.
ה - Assembly של ה - AJAX צריך לשבת ב - GAC. אפשר כמובן לשים את ה - dll בספריית ה - bin. אבל מה? כותב לו סקוט היקר, למר אלן ששאל האם ניתן להשתמש בפקדים מבלי להתקינם על השרת:
Hi Alan,
We recommend deploying ASP.NET AJAX 1.0 in the GAC rather than the \bin directory. The main reason for this is so that in the event we need to-do updates (security fixes, critical updates, etc), we have a way to service/update it.
Our expectation is that hosters will move pretty aggresively to install the 1.0 release on ASP.NET 2.0 hosts. Now that it is at 1.0 and fully supported, there is no reason not to (and customers are demanding it).
If your app runs in full trust, then you can deploy into the \bin directory - but I'd really recommend keeping it in the GAC.
Hope this helps, Scott
מסקנה: לפני שאתם משתמשים ב - AJAX בדקו שהוא מותקן על השרת - או שניתן להתקינו (לפנות למארח או למנהל השרת ולבדוק מולו).
-
התעסקות עם הפקדים
הבעיה העיקרית היא התיעוד. ושוב אני מדבר על ה - Ajax Toolkit, אין לזה תיעוד. פשוט כך. אם תכנסו לאתר - תוכלו לראות דוגמאות לפקדים - ודוגמה לקוד שיוצר את הדוגמה הזו. וזהו - בזה מסתכם התיעוד. אם תרצו לשנות משהו - ואף הכי קטן - כדאי שתכינו את עצמכם למסע ארוך בנבכי פורומים והודעות אינסופיות.
זה בקצרה מה שיש לי לומר על הפקדים - אם אתם מבינים את החסרונות, ותוכלו לפתור את אלו - לכו על זה, כי מעבר לזה מדובר על פקדים טובים.
אם נושא הגיבויים לא חשוב לכם, כנראה שאתם לא מתכנתים, ובגלל שהבלוג הזה מיועד למתכנתים - אז החלטתי לכתוב על גיבויים, איך ולמה.
אז למה לגבות, אם אפשר בעצם פשוט להיות יותר מסודרים? שלוש סיבות:
- מחקרים מגלים כי בני אדם טועים.
- מחקרים מגלים כי יש בתוכנות באגים.
- מחקרים מגלים כי חומרה יכולה "ללכת לעזאזל".
טוב, אז עכשיו אחרי שהוכחתי שגיבוי זה דבר חשוב, עם תמיכה ממחקרים שונים שאספתי, נגיע לעיקר - איך מגבים בקלות ובבטחה.
את התכנה הזו גיליתי כשקראתי את הפוסט תוכנות מועילות שחובה לכל מתכנת בבלוג של ג'סטין (אחלה תוכנות ואחלה פוסט - ממליץ לקרוא).
על התכנה הזו אין הרבה מה לכתוב, אז אני אסכם בקצרה:
תכנה חינמית לגיבוי קבצים וסנכרון, יכולה לגבות לכוננים שונים, ל - FTP, לכווץ את הגיבוי, להתריע אם נמחקו קבצים מהמקור, לרוץ ברקע אם רוצים ולתזמן גיבוי לפי תאריך/שעה או לפי מרווחי זמן, ועוד ועוד...
היא נורא פשוטה להפעלה ולא כבדה בכלל - אז למה אתם מחכים? הורידו אותה כבר עכשיו!
Subversion היא כלי די גדול וחזק לניהול גרסאות, רגע, לפני שאתם לוחצים על הלינק, נבהלים ומוותרים על הרעיון - כדאי שתקראו את הפוסט הזה עד סופו.
בגדול כלים לניהול גרסאות הם כלים יקרים ומסובכים, Subversion למזלינו היא תכנת קוד פתוח. מה שכן, היא לא פשוטה בכלל, כמו שאר התכנות.
ניהול גרסאות זה דבר חשוב מבחינתי לפחות - כי קרה לי בעבר שעשיתי שגיאות רציניות, ומה שקרה זה - שלאחר שעשיתי אותן - גיביתי את הקבצים - ואז אין ממש דרך חזרה. טוב שיש כלים לניהול גרסאות.
אז לפני שאם תוהים אם בכלל כדאי להתעסק עם כלים מסובכים - או מתחילים לקרוא את הספר של Subversion, לאחר חיפוש קצר ושיטוט באינטרנט מצאתי את המאמר הזה, שמסביר איך אפשר להתקין על המחשב שלך (למערכות הפעלה Windows XP, 2000 ו - 2003) Subversion בפחות מעשר דקות ובצעדים נורא פשוטים.
אחרי שאתם מתקינים Subversion, אני מניח שאתם לא רוצים להריץ אותו מחלון ה - Command כל פעם, בשביל זה קיימות שתי תוכנות נורא פשוטות, שהן תוכנות ה - Client של ה - Subversion.
תכנה וותיקה וטובה לעבודה מול Subversion ב - Windows (היא פשוט יושבת על ה - explorer של ה - Windows)
תכנה חדשה יחסית - ולמזלינו כבר יצאה גרסה יציבה - שמתממשקת ל - Visual Studio 2005, מאוד נוחה וטובה.
3. סוף דבר
זהו, עכשיו כל שנותר הוא להוסיף את הלינקים למועדפים, ולגבות את המועדפים. ולמתכנתים החדשים מבינכם, אלו שלא מגבים - תתחילו לגבות - גיבוי זה דבר חשוב!