none
האם הגישה שלי נכונה עבור Data Access Layer

    שאלה

  • שלום לכולם,

    אני מפתח פרויקט שבהגדרתו אמור לתת מענה לתעבורת רשת גבוהה ומבנה נתונים מורכב, עכשיו עד היום בפרויקטים שפיתחתי הייתי משתמש ב-EF לפרויקטים בינוניים ובפרויקטים פשוטים ADO.NET עם כמות לא גבוהה במיוחד של סטורד פרוסיג'רס...

    עכשיו אני מודע לחסרונות של EF בפרויקטים גדולים שכן הדבר הביא אותי לכיוון חשיבה כזה:

    אני רוצה לשמר את קלות השימוש של EF, אך אני זקוק לביצועים מהירים ללא קוד מיותר של התשתית, עם זאת אני לא רוצה סלט של סטורד פרוסיג'רס במסד הנתונים שכל שאילתא פשוטה כמו SELECT * FROM Users סתם תתפוס סטורד פרוסיג'ר... אני מעריך שזה ייצור בלאגן וקושי בתחזוקה.

    אז אמרתי, אפשר לפתח ספריית עזר שבעזרתה יהיה ניתן "לבנות" שאילתות מאחורי הקלעים ע"י בניית אובייקט שיגדיר את השאילתא, וכאשר האובייקט יהיה בנוי, הוא ישלח ל-1 מתוך 4 סטורד פרוסיג'רס כתובים מראש במסד הנתונים (4 עבור CRUD, כל אחד מייצג מבנה שאילתא שונה: CREATE, READ, UPDATE, DELETE), וכאשר יגיע אובייקט השאילתא (שנבנה מספריית העזר) אל אחד מה-SP הוא ידע לתרגם אותו לשאילתא ממשית במסד הנתונים, להריץ אותה ולהחזיר את הרשומות בהתאם. יש לציין שכל אחת מהפרוצדורות מבצעות פעולות רבות כדי "לפענח" את האובייקט שמגיע מהספרייה ונידרש לבצע בהן לולאות, משתנים קבועים וזמניים הנוצרים בפרוצדורה, טבלאות זמניות הנוצרות, בדיקות רבות לפרמטרים וכו'...

    הדבר אמור לסייע רק לשאילתות פשוטות-בינוניות, עבור שאילתות מורכבות יהיה סטורד פרוסיג'ר ייעודי. זה נותן מענה לסלט הפרוצדורות שנוצר משאילתות פשוטות.

    לכן, זקוק לעזרתכם מה דעתכם לגבי הגישה הזאת? והאם אתם מכירים גישות טובות יותר עבור ה-Data Access Layer בפלטפורמות גדולות?

    הפרויקט מפותח בסביבת MVC 6 ומסד הנתונים הינו SQL Server 2016

    תודה לעוזרים.

    יום ראשון 07 מאי 2017 21:35

תשובות

  • אהלן,

    קודם כל תודה רבה על הסבר מפורט ומעמיק :-)

    אני אתמקד בהמלצה שלך לא להשתמש בשום ORM על מנת להשיג ביצועים טובים יותר...

    נניח שאני לא אשתמש בשום ORM, למיטב ידיעתי כל שאילתא תצטרך לתפוס סטורד פרוסיג'ר משלה והדבר מוביל אותי לחשיבה על סלט של סטורד פרוסיג'רס שקשה לתחזק... השאלה אם לא זאת הכוונה שלך? שכן אני לא מכיר דרך אחרת לבצע שאילתות בדרך בטוחה ללא חשש ל-Injection  מבלי לבצע זאת ע"י פרוצדורות או דרך ORM

    תודה על התגובה :-)

    היי

    >> אני אתמקד בהמלצה שלך לא להשתמש בשום ORM על מנת להשיג ביצועים טובים יותר...

    זה מחייב יכולת של DBA כמובן בכתיבה וניהול השאילתות

    >> למיטב ידיעתי כל שאילתא תצטרך לתפוס סטורד פרוסיג'ר

    לפני שאני צועק "ממש לא נכון" אני חייבלעצוררגע ולדון בנושא Off Topic

    אני שונא כאשר כותבים מילים בשפה אחת בעזרת שפה אחרת. זה לפעמים הוך את התוכן לממש בילתי קריא. אם אתה רוצה לרשום מילה באנגלית כמו stored Procedure אז למה אתה מנסה לכתוב אותה בעברית? עברית אולי שפה יפה אבל בחרת במילה באנגלית

    הדרך הנוכנה היא כמובן לאלערבב שפות ולדבר בעברית, אם אפשר (לא כל המילים במקצוןעיות ניתנות לתרגום).

    Stored Procedure = פרוצדורה שמורה :-)

    נחזור לצעקה של ממש לא! אתה טועכה לחלוטין

    אני מאוד ממליץ לעבור על מדריכים של פיתוח הכוללים גישה למסד נתונים. השימוש בשאילתות ישירות היא הדרך הנפוצה וגם הנכונה לרוב המצבים.

    >> שכן אני לא מכיר דרך אחרת לבצע שאילתות בדרך בטוחה ללא חשש ל-Injection  מבלי לבצע זאת ע"י פרוצדורות או דרך ORM

    זו שאלה שונה לחלוטין מהקודמת.מעל דנו בהאם ה אפשרי ועתהאמנחנו דנים בדרך הנכונה לביצוע

    הזרקת שאילתות היא תופעה ישנה שפוגת רק במערכות שמפותחת ברמה מאוד מאוד... מאוד נמוכה ואינה קשורה בכלום לשימוש ב ST (השם המקוצר לפרוצדורה שמורה). זה נכון שהרבה מדריכים ברמה נמוכה מדברים על כך שהפתרון הוא שימוש בפרוצשורה שמורה מכיוון שפרוצשורה שמורה תוכל לקבל פרמטרים אבל דם שאילתות יכולות לקבל פרמטרים!

    העבודה הנוכנה היא ישרות אם שאילתות בעזרת פרמטרים ולא על ידי כתיבת שאילתה בצורה של חיבור טקסטים

    זה אסור לביצוע!!!

    select x,y from MyTable where x=" + Parameter + " and..."

    במקרה מעל אנחנו משרשרים ערכים ליצירת השאילתה ולכן אנחנו חשופים להזרקת שאילתות. מישהו יכול להחליף את הערך של הפרמטר בשרשרת כלשהיא ולאחר שרשור הפרמטר נקבל שאילתה שונה. למשל אם הפרמטר יקבל את הערך הבא

    Parameter = "x; Drop table MyTable; select 1 where a = 1 "

    עתה נסה לחברשרשראות טקס וקיבלת הזרקת שאילתה שגורמת למחיקת הטבלה

    הדרך הנכונה היא לעבוד עם פרמטרים

    יש לך כאן מדריך בסיס נחמד לדוגמה. אניח ממליתץ לא לקפוץ לביום אלא לעבור שורה אחרי שורה ולקרוא הכל!
    https://www.codeproject.com/Articles/823854/How-to-connect-SQL-Database-to-your-Csharp-program

    כאשר תגיע לחלק שדן ב Parameterizing the data תוכל לראות את הפתרון הנכון לבעיה מעל

    כאמור אין משמעות להזרקת שאילתות כר הרבה שנים ומי שלא יודע לעבוד עם פרמטרים אין לו מקום בעבודה עם מדי נתונים ושאילתות. זה נקודה שנילמדת בכל מדריך ובכל קורס בסיסי. זה מצביע על כך שאתהלמדת כניראה לבד בצורה לא מסודרת וחבל מאוד. אני ממליץ לבחור ספר טוב או מדריך באינטרנט טוב וללמוד בצורה מסודרת.

    אין הזרקת שאילתות כאשר עובדים עם Parameterizing the data מכיוון שהערך שלהפרמטר מועבר כיחידה אחת ולא מפורק כטקסט


    signature   Ronen Ariely
     [Personal Site]    [Blog]    [Facebook]    [Linkedin]


    • נערך על-ידי pituachMVP, Editor יום שני 08 מאי 2017 20:28
    • סומן כתשובה על-ידי ohad12131 יום שני 08 מאי 2017 21:22
    יום שני 08 מאי 2017 20:28
    מנחה דיון

כל התגובות

  • שלום לכולם,

    אני מפתח פרויקט שבהגדרתו אמור לתת מענה לתעבורת רשת גבוהה ומבנה נתונים מורכב, עכשיו עד היום בפרויקטים שפיתחתי הייתי משתמש ב-EF לפרויקטים בינוניים ובפרויקטים פשוטים ADO.NET עם כמות לא גבוהה במיוחד של סטורד פרוסיג'רס...

    עכשיו אני מודע לחסרונות של EF בפרויקטים גדולים שכן הדבר הביא אותי לכיוון חשיבה כזה:

    אני רוצה לשמר את קלות השימוש של EF, אך אני זקוק לביצועים מהירים ללא קוד מיותר של התשתית, עם זאת אני לא רוצה סלט של סטורד פרוסיג'רס במסד הנתונים שכל שאילתא פשוטה כמו SELECT * FROM Users סתם תתפוס סטורד פרוסיג'ר... אני מעריך שזה ייצור בלאגן וקושי בתחזוקה.

    אז אמרתי, אפשר לפתח ספריית עזר שבעזרתה יהיה ניתן "לבנות" שאילתות מאחורי הקלעים ע"י בניית אובייקט שיגדיר את השאילתא, וכאשר האובייקט יהיה בנוי, הוא ישלח ל-1 מתוך 4 סטורד פרוסיג'רס כתובים מראש במסד הנתונים (4 עבור CRUD, כל אחד מייצג מבנה שאילתא שונה: CREATE, READ, UPDATE, DELETE), וכאשר יגיע אובייקט השאילתא (שנבנה מספריית העזר) אל אחד מה-SP הוא ידע לתרגם אותו לשאילתא ממשית במסד הנתונים, להריץ אותה ולהחזיר את הרשומות בהתאם. יש לציין שכל אחת מהפרוצדורות מבצעות פעולות רבות כדי "לפענח" את האובייקט שמגיע מהספרייה ונידרש לבצע בהן לולאות, משתנים קבועים וזמניים הנוצרים בפרוצדורה, טבלאות זמניות הנוצרות, בדיקות רבות לפרמטרים וכו'...

    הדבר אמור לסייע רק לשאילתות פשוטות-בינוניות, עבור שאילתות מורכבות יהיה סטורד פרוסיג'ר ייעודי. זה נותן מענה לסלט הפרוצדורות שנוצר משאילתות פשוטות.

    לכן, זקוק לעזרתכם מה דעתכם לגבי הגישה הזאת? והאם אתם מכירים גישות טובות יותר עבור ה-Data Access Layer בפלטפורמות גדולות?

    הפרויקט מפותח בסביבת MVC 6 ומסד הנתונים הינו SQL Server 2016

    תודה לעוזרים.

    אהלן

    בוא נעבור על כמה נקודות:-)

    >> אני זקוק לביצועים מהירים ללא קוד מיותר של התשתית

    מערכות ORM כמו EF לא יוצרות קוד מיותר אלא קוד לא יעיל בדרך כלל. אני מניח שאתה מגיע מתחום הפיתוח ופחות מחובר לשרת מסדי הנתונים (SQL Server למשל) ולכיצד הוא עובד מאחורי הקלעים. באופן פשטני וקצר מאוד, השרת לא מריץ את השאילתות שאתה שולח אליו אלא תמיד מייצר תוכנית הרצהבה הוא יכול לעשות שימוש פעמים רבות. שאילתות לא מיטביות יכולות לגרור תוכניות הרצה לא יעילות ולכן ריצה שעולה לנו ביותר משאבים. מערכות ORM עושות למפתח את החיים קלים מכיוון שהוא כביכול לאצריך לכתוב את השאילתות אבל התשלום באוטומציה היא שמחסור ביכולת לחשוב שיש לכל DBA שהיה כותב את השאילתות. התוצאה היא שמערכות ORM לא תמיד יוצרות את השאילתות המיטביות

    DBA ממוצע אמור להצליח בקלות ליצור שאילתות הרבה יותר יעילות מאלו שנוצרות בEF בבריררת המחדל 

    אבל כאן מגיעים לשלב המתקדם... לא תמיד חייבים לעבוד בברירת המחדל

    מפתח שהינו גם DBA טוב יוכל להטות את ה EF ליצירת שאילתות מיטביות, אבל העבודה יכולה להיות הרבה הרבה... הרבה יותר ארוכה מכתיבת השאילתות ישירות ולכן אין בכך הגיון. כל הרעיון של שימוש ב ORM זה לחסוך זמן פיתוח ולכן אם מיטוב לוקח יותר זמן מכתיבה ישירה אנחנו פונים לכתיבה ישירה

    >> אפשר לפתח ספריית עזר שבעזרתה יהיה ניתן "לבנות" שאילתות מאחורי הקלעים

    כמובן שלא צריך להמציא את הגלגל :-)

    EF מאפשר להריץ שאילתות ישירות בלי צורך לפתח ספריות שלך לצורך העניין. אתה לא הראשון שהבין את הבעיה וכתב את הפתרון (מובנה בסביבת EF ונכתב על צוות ה EF שהבינו את הבעיה): https://msdn.microsoft.com/en-us/library/jj592907%28v=vs.113%29.aspx

    >> "לבנות" שאילתות מאחורי הקלעים ע"י בניית אובייקט שיגדיר את השאילתא, וכאשר האובייקט יהיה בנוי, הוא ישלח ל-1 מתוך 4 סטורד פרוסיג'רס כתובים מראש במסד הנתונים (4 עבור CRUD, כל אחד מייצג מבנה שאילתא שונה: CREATE, READ, UPDATE, DELETE), וכאשר יגיע אובייקט השאילתא (שנבנה מספריית העזר) אל אחד מה-SP הוא ידע לתרגם אותו לשאילתא ממשית במסד הנתונים, להריץ אותה ולהחזיר את הרשומות בהתאם.

    מה שאתה מתאר כאן זה לפתח מערכת ORM שלך :-)

    זה אפשרי וישנם הרבה מאוד מערכות ORM בשוק, כמו למשל NHibernate או Drapper. אתה לא חייב לעבוד עם EF (אם כי הוא חד משמעית הטוב ביותר למי שמפתח בדוט-נט ועובד עם שרתי SQL Server). השאלה הגדולה היא, האם אתה כרגע נמצא בנקודת הידע המתאימה?!? פיתוח ORM מחייב שליטה גבוהה מאוד גם בצד הפיתוח וגם בצד של ה שרת מסדי נתונים. מה גם שמדובר בעבודה מאוד מאוד ארוכה ומייגעת שיכולה לקחת שנים רבות של פיתוח.

    בקיצור, כלל הזהב שלי הוא לא להשתמש בשום ORM, אבל אם ממש ממש ממש יש סיבה לכך אז EF כולל אפשרות לעבודה עם שאילתות ישירות

    אני מקווה שזה היה תקציר מועיל :-)


    signature   Ronen Ariely
     [Personal Site]    [Blog]    [Facebook]    [Linkedin]

    יום ראשון 07 מאי 2017 21:55
    מנחה דיון
  • אהלן,

    קודם כל תודה רבה על הסבר מפורט ומעמיק :-)

    אני אתמקד בהמלצה שלך לא להשתמש בשום ORM על מנת להשיג ביצועים טובים יותר...

    נניח שאני לא אשתמש בשום ORM, למיטב ידיעתי כל שאילתא תצטרך לתפוס סטורד פרוסיג'ר משלה והדבר מוביל אותי לחשיבה על סלט של סטורד פרוסיג'רס שקשה לתחזק... השאלה אם לא זאת הכוונה שלך? שכן אני לא מכיר דרך אחרת לבצע שאילתות בדרך בטוחה ללא חשש ל-Injection  מבלי לבצע זאת ע"י פרוצדורות או דרך ORM

    תודה על התגובה :-)


    יום ראשון 07 מאי 2017 22:44
  • אהלן,

    קודם כל תודה רבה על הסבר מפורט ומעמיק :-)

    אני אתמקד בהמלצה שלך לא להשתמש בשום ORM על מנת להשיג ביצועים טובים יותר...

    נניח שאני לא אשתמש בשום ORM, למיטב ידיעתי כל שאילתא תצטרך לתפוס סטורד פרוסיג'ר משלה והדבר מוביל אותי לחשיבה על סלט של סטורד פרוסיג'רס שקשה לתחזק... השאלה אם לא זאת הכוונה שלך? שכן אני לא מכיר דרך אחרת לבצע שאילתות בדרך בטוחה ללא חשש ל-Injection  מבלי לבצע זאת ע"י פרוצדורות או דרך ORM

    תודה על התגובה :-)

    היי

    >> אני אתמקד בהמלצה שלך לא להשתמש בשום ORM על מנת להשיג ביצועים טובים יותר...

    זה מחייב יכולת של DBA כמובן בכתיבה וניהול השאילתות

    >> למיטב ידיעתי כל שאילתא תצטרך לתפוס סטורד פרוסיג'ר

    לפני שאני צועק "ממש לא נכון" אני חייבלעצוררגע ולדון בנושא Off Topic

    אני שונא כאשר כותבים מילים בשפה אחת בעזרת שפה אחרת. זה לפעמים הוך את התוכן לממש בילתי קריא. אם אתה רוצה לרשום מילה באנגלית כמו stored Procedure אז למה אתה מנסה לכתוב אותה בעברית? עברית אולי שפה יפה אבל בחרת במילה באנגלית

    הדרך הנוכנה היא כמובן לאלערבב שפות ולדבר בעברית, אם אפשר (לא כל המילים במקצוןעיות ניתנות לתרגום).

    Stored Procedure = פרוצדורה שמורה :-)

    נחזור לצעקה של ממש לא! אתה טועכה לחלוטין

    אני מאוד ממליץ לעבור על מדריכים של פיתוח הכוללים גישה למסד נתונים. השימוש בשאילתות ישירות היא הדרך הנפוצה וגם הנכונה לרוב המצבים.

    >> שכן אני לא מכיר דרך אחרת לבצע שאילתות בדרך בטוחה ללא חשש ל-Injection  מבלי לבצע זאת ע"י פרוצדורות או דרך ORM

    זו שאלה שונה לחלוטין מהקודמת.מעל דנו בהאם ה אפשרי ועתהאמנחנו דנים בדרך הנכונה לביצוע

    הזרקת שאילתות היא תופעה ישנה שפוגת רק במערכות שמפותחת ברמה מאוד מאוד... מאוד נמוכה ואינה קשורה בכלום לשימוש ב ST (השם המקוצר לפרוצדורה שמורה). זה נכון שהרבה מדריכים ברמה נמוכה מדברים על כך שהפתרון הוא שימוש בפרוצשורה שמורה מכיוון שפרוצשורה שמורה תוכל לקבל פרמטרים אבל דם שאילתות יכולות לקבל פרמטרים!

    העבודה הנוכנה היא ישרות אם שאילתות בעזרת פרמטרים ולא על ידי כתיבת שאילתה בצורה של חיבור טקסטים

    זה אסור לביצוע!!!

    select x,y from MyTable where x=" + Parameter + " and..."

    במקרה מעל אנחנו משרשרים ערכים ליצירת השאילתה ולכן אנחנו חשופים להזרקת שאילתות. מישהו יכול להחליף את הערך של הפרמטר בשרשרת כלשהיא ולאחר שרשור הפרמטר נקבל שאילתה שונה. למשל אם הפרמטר יקבל את הערך הבא

    Parameter = "x; Drop table MyTable; select 1 where a = 1 "

    עתה נסה לחברשרשראות טקס וקיבלת הזרקת שאילתה שגורמת למחיקת הטבלה

    הדרך הנכונה היא לעבוד עם פרמטרים

    יש לך כאן מדריך בסיס נחמד לדוגמה. אניח ממליתץ לא לקפוץ לביום אלא לעבור שורה אחרי שורה ולקרוא הכל!
    https://www.codeproject.com/Articles/823854/How-to-connect-SQL-Database-to-your-Csharp-program

    כאשר תגיע לחלק שדן ב Parameterizing the data תוכל לראות את הפתרון הנכון לבעיה מעל

    כאמור אין משמעות להזרקת שאילתות כר הרבה שנים ומי שלא יודע לעבוד עם פרמטרים אין לו מקום בעבודה עם מדי נתונים ושאילתות. זה נקודה שנילמדת בכל מדריך ובכל קורס בסיסי. זה מצביע על כך שאתהלמדת כניראה לבד בצורה לא מסודרת וחבל מאוד. אני ממליץ לבחור ספר טוב או מדריך באינטרנט טוב וללמוד בצורה מסודרת.

    אין הזרקת שאילתות כאשר עובדים עם Parameterizing the data מכיוון שהערך שלהפרמטר מועבר כיחידה אחת ולא מפורק כטקסט


    signature   Ronen Ariely
     [Personal Site]    [Blog]    [Facebook]    [Linkedin]


    • נערך על-ידי pituachMVP, Editor יום שני 08 מאי 2017 20:28
    • סומן כתשובה על-ידי ohad12131 יום שני 08 מאי 2017 21:22
    יום שני 08 מאי 2017 20:28
    מנחה דיון
  • עשית לי הרבה סדר בדברים... תודה רבה על התשובות. :-)
    יום שני 08 מאי 2017 21:22
  • בכיף, אני שמח שיכולתי לעזור :-)


    signature   Ronen Ariely
     [Personal Site]    [Blog]    [Facebook]    [Linkedin]

    יום שני 08 מאי 2017 23:31
    מנחה דיון