איך כדאי להשתמש ב entityFramework

batchenco

New member
איך כדאי להשתמש ב entityFramework

שלום יש לי בקשה ארוכה ואני מקווה שלמשיהו יהיה זמן לקרוא את זה ולענות לי - אשמח מאד אם משיהו יוכל להסביר לי .....
שלום אני מפתחת ב EF 5
ואני מתלבטת מה הצורה הנכונה והיעילה לעבוד איתו ?
האם יש שכבה אחת שאחראית על ה DB וה datamodel
ומעלה יש שכבה BI - שהיא ממירה את האובייקטים שמגיעים מה DB לאובייקטים אחרים שישמשו בפועל להצגה - ושם יהיו פונקציות כגון getAllChild וכ' .
ואז יש שכבה של GUI - שמציגה את הנתונים שבה יש בפועל את הפרוייקט ה web .

--- אם אני משתמשת בשיטה הזאת - אז כאשר אני שולפת 1000 אובייקטים ויותר. ההמרה בין האובייקטים שהגיעו מה DB לאובייקטים שאני רוצה להציג לוקחת הרבה זמן - כמעט דקה ל500 אובייקטים .
השאלה איך באמת עובדים עם ה EF ? האם צריכים את ההמרה הזאת? ואם לא אז איך כן משתמשים אם אני רוצה להציג אובייקט במבנה שונה ממה שנמצא בבסיס הנתונים
 

nocgod

New member
למה EF5? הגרסא האחרונה היום נראה לי 6.1.3 (יציבה) ו 7beta8

קשה מאוד להחליט על צורת עבודה נכונה עם EF באופן כללי, כי אין דרך אחת נכונה, כולן שגויות =)

באופן כללי איך אני הייתי עושה את זה

כדי להבין מה לוקח כל כך הרבה זמן instansiation של אובייטים חדשים, תעשי profiling באמצעות dotTrace או משהו (תורידי לתקופת התנסות)

באופן כללי - יכול לקחת לך המון זמן גם אם את כל הזמן עושה recreate ל DbContext שלך, הוא אובייקט שאמור לשמש אותך לאורך חיים לא קצר מידי, אבל גם לא ארוך מידי כדי להזדהם ולצאת מסנכון עם הDb, מה שבטוח לא לייצר dbContext עבור כל משיכה של כל אובייקט, זו טעות.

ב ef6 נוסף async API שיכול אולי להועיל לך קצת, מביאה מידע בצורה אסינכרונית וברגע שחלקים ממנו נהיים נגישים עבורך - את ממירה אותם בזמן שחלקים אחרים ממשיכים להגיע (אולי זה לא יעזור)

אגב שכבת ה BL לא אמורה להכיר את ה entities אם את משתמשת מחלקות מקושטות עם attributes כי אז הBL יהיה תלוי ב EF וזה מיותר לחלוטין.

באופן כללי, אם אין הכרח אמיתי להמיר את הentities שלך מה data model ל contracts אחרים, אין סיבה לעשות את זה (שוב כל עוד ה entities לא מקושטים ומנסים לעשות decoupeling בין ה DAL ל BI בצורה איכותית - מה שלא תמיד קל עם EF לצערי)
 
הערה כללית

לפי שאלותייך, חסר לך ידע בסיסי ב EF. זה כלי קל מאד לעבודה, שבעצם נוצר כדי להקל עלינו המתכנתים את העבודה. אבל, צריך לדעת את הכללים. ממליץ לך לקחת קורס (לדוגמה בפלורלסייט) על EF, כמובן גרסה 6 ולא 5, חפשי גברת בשם ג'ולי לרמן. היא הסמכות העולמית בכל מה שקשור ל EF, וגם אשה מאד נחמדה ומסבירה יפה ובצורה ברורה. כל מה שאני יודע על EF למדתי ממנה. יש לה גם ספרים טובים.
לסיכום: לא נעשה ונשמע, אלא קודם נשמע (ונבין) ואחר כך לעשות יהיה יותר קל. בהצלחה.
 
לאיזו סביבה את מפתחת?

אם את מפתחת web, קראי את המדריכים הרשמיים של asp.net. הם ברורים, פשוטים, טובים ומעולים.
במחשבה שניה, גם אם את מפתחת wpf או משהו אחר, כדאי לקרוא את המדריכים האלו, כי הם טובים מאד. ואם על הדרך תלמדי גם כמה מושגים בmvc, לא תצטערי על כך.

כמה הערות:
1. נדמה לי שמקובל היום לא לכתוב שכבה נוספת מעל המודל, אלא להשתמש ישירות באובייקטים של המודל. nocgod טוען שזה בעיתי להשתמש בattributes של המודל, אבל לדעתי אין הוא צודק. אדרבא. mvc בנוי מלכתחילה שהview משתמש attributes האלו.
2. בוודאי תראי הרבה מדריכים מיושנים שעובדים עם repositories. אין בזה צורך, EF הוא בעצמו repository ואפשר להשתמש בו עצמו בלי עטיפות ובלי שכבות.
 

nocgod

New member
אני לא טוען שזה בעייתי, אני טוען שאני לא אוהב

ושאם רוצים לעשות הפרדה בין DAL ל BL ויש לך מודל עם attributes של EF עליו אז גם ה BL יהיה תלוי ב EF, מה שפוגע בהפרדה שרצית לייצר.
אני בעד programatic mapping כשצריך ומעדיף בכלל לכתוב לפי קונבנציות ואז לא צריך mapping ולא כלום.
כמובן שאם אפשר להשתמש באובייקט מודל לאורך כל התוכנה זה מעולה ואפילו רצוי כדי להמנע ממצבים של detachment מ context ואז re-attachment או ייצור אובייקטים מחדש עם שדה פחות.

ובכלל הפוסט ששלחתי בהודעה הקודמת מסביר, לדעתי, את הדרך הכי נכונה לעבוד עם EF בצורה אופטימלית.
 
מה הבעיה בAttributes?

הם אינם יוצרים שום תלות בEF, ואין להם שום קשר לEF.
הAttributes שייכים לאסמבלי <font><font>System.ComponentModel.DataAnnotations </font></font>שהוא חלק מדוט נט.

גם מבחינה לוגית, הAtts אינם שייכים בהכרח לEF. למשל Required או Length, שגם הView משתמש בהם כדי לעשות וולידציה.
אמנם יש את Column וכו', שהם הוראות איך למפות את המודל לדטהבייס, אבל למי זה מפריע?! למה זה שובר את ההפרדה בין השכבות?!

מקרה שימושי: יש לי סרוויס וקליינט ששניהם צריכים להכיר את אותם מודלים. אני כותב את המודלים בפרוייקט נפרד שמשותף גם לסרוויס וגם לקליינט. את הDbContext אני שם בסרוויס. לפרוייקט המשותף אין רפרנס לEF, וזה לא מפריע לקשט את המודלים בAtts.


המאמר שהבאת הוא מאמר מעמיק שדן במקרים מסובכים. לפני כמה חודשים שקלתי את הפתרון שלו [DbContextScope], אבל בסוף זנחתי את זה כי לא רציתי להשתמש בפרקטיקות שרוב העולם לא מכיר.
אגב, בasp.net 5 יוצרים תמיד את הקונטקסט לכל request. הסיבה, מכיוון שהקונטקסט איננו thread safe, מחזור החיים שלו צריך להיות קצר ככל האפשר. אינני יודע איך הם מתמודדים עם בעית הביצועים [הזמן שלוקח לאתחל את הקונטקס]
 

nocgod

New member
לא כל האנוטציות בואות מהassembly הזה

עד כמה שאני זוכר חלק מאנוטציות שייכות ל assemblies של ה EF
למה זה שובר? זה גורם ל BL להיות תלוי טרנזיטיבית ל EF שלך כי ה models תלויים ב EF.

לגבי אורך החיים של ה context, כמו שאמרתי לא צריך להיות ארוך מידי ולא קצר מידי. כשמדובר ב web אני תמיד משתמש ב PerWebRequest lifestyle כדי לדאוג שמצד אחד כל הישויות עבור אותה הבקשה יהיו מחוברות לcontext מצד שני שלא תהיה התיישנות אם אתה משמר ctx בין בקשות
 
לא ברור

אתה חוזר על הטענה אבל אני עונה לך: התלות היא חד-סטרית. EF תלוי במודל אבל המודל איננו תלוי בEF.
גם אם יש במודל Attributes עם הוראות מיפוי לEF, זה לא יוצר תלות בEF.
קל וחומר כאשר את כל המיפוי עושים בתוך הקונטקסט [OnModelCreation]

*כל* הatts הם חלק מדוט נט למעט IndexAttribute ואולי עוד כמה לא שימושיים.
OnModelCreation
 

Sea Bass

New member
אני טיפה מופתע

שאתה חושב שקיווץ כל הקוד של המערכות אמורה להסתכם בפרוייקט אחד.
לא כל מוצר של חברה מסתכם באתר WEB מסויים והצגת נתונים סטטים או דינמים.
כשיש לך מספר מערכות שצריכות לבצע עבודה ב Schdule, Notification שימוש ב queue שימוש ב Ftp וכו וכו..
לממש הכל בפרוייקט אחד זה לא רציני.
למה שמערכת שצריכה נניח לשלוח הודעות ללקוחות סתם לדוגמא, תשתמש בפרוייקט שיש בו קוד שלם לשליחת קבצים ב FTP?
לפי התיאוריה שלך (עד כמה שאני מבין) גם אם מדובר במגה חברה, עם מאות מערכות, הכל מסתכם בפרוייקט אחד ששם יש את כל הקוד?
 
>

ראשית, ביחס למודל. גם אם אתה כותב הרבה פרוייקטי סרוויס, המודל יכול להיות משותף. יש בעיה לשתף את כל המודלים ברחבי כל הפרוייקטים של החברה?!

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

ביחס לסרוויס, אין באמת בעיה לכלול הכל בפרוייקט אחד. ניקח את MVC: כל קונטרולר הוא בעצם סרוויס עצמאי לכל דבר. אתה יכול להפריד כל קונטרולר לפרוייקט נפרד, אבל אין בזה טעם. אז אם יש לי אלף קונטרולרים, יש בזה בעיה? אלפיים קונטרולרים?
אתה צודק כאשר יש סרוויסים שונים שמתפקדים למטרות שונות. למשל: האתר של בנק הפועלים הוא סרוויס אחד, והכספומטים מחוברים לסרוויס אחר. שני הסרוויסים האלו משתמשים בסרוויס משותף כדי להעביר כסף מחשבון לחשבון.
 

Sea Bass

New member
הנה

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

nocgod

New member
התלויות ב #C הן טרנזיטיביות ידידי

Model references EF to have some attributes
Logic references Model
trasitively Logic must be dependant on EF to supply Model with its dependencies.

משמעו אם אתה עושה reference מlogic ל model יהיה לך DLL של EF בתיקיית ה bin של Logic למרות של Logic לכשעצמו אין שום סיבה להכיר אותו, הוא עדיין חייב להטען בזמן ריצה כדי שהקוד יכיר את ה attributes הבודדים שאם משתמשים בהם אז צריך את EF.
בגלל זה לרוב הפרוייקטים שלי היו מחולקים ככה
  • App layer - references interfaces, contracts and DI
  • Logic layer - references Interfaces and implement ILogic, knows IDal and contracts
  • Interfaces - knows no one
  • DI - knows interfaces, loads assemblies dynamically from working dir and registers by convention (may know concrete types statically). worst case scenario - App layer knows interfaces and statically registers implementations of the other layers (constructs the application so to say)
  • Contracts - DTOs and API contracts, knows nothing (john snow)
  • DAL - EF, Data models, implements IDal
ככה:
א. מגדילים ניתוק של רכיבים
ב. מגדילים אפשרות לשמש מחדש קוד
ג. מגדילים את הרמת ה"בדיקות" של הקוד (unit testing + DI)
ד. השכבות לא תלויות אחת בשניה אלא בסט אבסטרקציות
ה. אפשר להחליף כל שכבה בשכבה אחרת כל עוד הן מממשות את האבסטרקציות הנחוצות

כאשר הפיתרון שהביא Mehdi נותן לך באמצע את המסמר האחרון והוא היכולת להפריד לחלוטין את הקוד ב BL לבין הקוד ב EF. כי עם כל הכבוד רק ישות אחת יכולה להתחיל business transaction ולסיים (כלומר לעשות את הcommit) אותה וזה ה BL ולא ה DAL.
 
מוזר מאד

מנסיוני האישי, אין שום בעיה כזו. אם אתה משתמש בAttributes הבודדים של EF, אז תוריד אותם ותעשה את הקונפיגורציה בקונטקסט.
אפילו אם אי אפשר לוותר על הAttribute, אז תן ללוגיק רפרנס לEF. אין בזה שום רע וזה לא שובר שום עקרון ושום DesignPattern.

אתה משכפל את כל המודל רק בגלל בעית הAttributes! זה הגיוני?! לשכפל מודל שלם ולתחזק אותו רק בגלל בעיה שולית וקטנה?!

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

אגב: הרבה פעמים ממילא צריך להוסיף רפרנסים. לדוגמא, נניח שיש לנו מבנה כזה:
MyApp- MyApp.View [startup project]
- MyApp.ViewModel [has depencency on Prism NuGet package]
- MyApp.Model [has dependency on EF/Dapper/ NuGet package]

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

nocgod

New member
אני לא בעד לשכפל, אני בעד לנקות אותם מאנוטציות מכוערות

כמו שאמרתי קודם אני מעדיף לעשות קונפיגורציה באמצעות קוד מאשר באמצעות attr, זה יותר אסטטי לדעתי בכל מה שקשור ל data models/contracts, לצורך העיניין אני לא סובל להוסיף DataContract/DataMember כדי ש azure יוכל לשלוח אובייקטים בסרוויס באס שלהם.
מצד שני, לא יצא לי לפתח API שבו הייתי צריך לחשוף את כל המודל אז תמיד בסופו של דבר ב API הייתה המרה לDTO כלשהו שהיה מייצג את את ה data model בצורה רזה או הרכבה של כמה מודלים על בקשה אחת (במקרה של מובייל כדי לחסוך בקשות followup)

ואין שום דבר רע בלעשות reference מפרוייקט BL לEF, אבל אז אתה עושה מתלה את הלוגיקה במשהו שלא אמור לעניין אותה בגלל קונפיגורצייה על ה data model שמגדירה איך לשמור אותו ב DB - משהו אני מעדיף להמנע ממנו כמה שיותר.

לסיכומה של השאלה של השואל המקורי - צריך לעשות profiling ולראות את הקוד שהוא עשה, כי ככה קשה לדעת מה הבעיה בקוד.
 

Sea Bass

New member
יש עוד משהו שצריך לדבר עליו

מלבד האורך חיים של ה Context.
בעבודה אצלי (וזה משהו שאני עכשיו עובד על מנת לשנות אותו לחלוטין) זה מצב שנוצר שיש שכבה אחת DAL נניח שמאגדת את כל האובייקטים של ה DB בתוכה.
זאת אומרת שאם רוצים להוסיף טבלה, מוסיפים עוד קלאס לפרוייקט הזה והוא כמובן משותף לכל. הטבלאות גודלות וגודלות וכך גם המודלים שם.
בנוסף לא קיים פה הפרדות ל Services שונים אלא Service אחד שמטפל בהכל הכל. מן GodService.
אני מתחיל מעובדה אחת! שאת המודלים שלי אני רוצה להצהיר בשכבה ה BL שלהם. אני יכול לבצע הפרדה יותר גסה שעל כל ServiceA , יהיה גם ServerDalA אבל זה נראה לי כבר יותר מידי.
מה אתם אומרים?
 
מה לא טוב?

אם יש לך דטהבייס בן אלף טבלאות, טבעי שבמודל יהיו אלף מחלקות.
אם יש לך כמה סכמות בדטהבייס, אתה יכול גם את המודל לחלק לnamespaces. בתוך התיקיה models צור תיקיות משנה לפי הסכמות שבדטהבייס.

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

nocgod

New member
אין בעיה ב DB עם מיליון טבלאות

יש בעיה עם service אחד שחושף ומכיר את כולן - זה god complex שמקשה לעשות scaling.
גם אם מדובר ב 100 קונטרולרים שכל אחד מכיר רק 100 טבלאות מתוך ה1000 טבלאות, אם כולם יושבים באותו ה service ז"א שכולם חולקים את אותה המכונה ואותם המשאבים, זה אומר שאם אחד הקונטרולרים מייצר bottlenecks בביצועים אתה לא יכול לעשות scaleup לאותו הקונטרולר או domain של קונטרולרים אלא צריך לעשות scale לא נדרש לכל ה service בשלמותו.

בכלל לא דיברתי על בעיה של ניהול קוד שהרבה ידיים נוגעות כל הזמן באותו הקוד (merge merge merge).

יש עם זה המון בעיות לדעתי, אבל כנראה שאנחנו רואים דברים בצורה שונה קצת.
בדיוק בשביל דברים כאלה הומצא ה micro-services לדעתי, הרבה סרוויסים קטנים מוכווני דומיין (חלקם יכולים לחלוק domain models כמובן) שמדברים ביניהם ובעצם מייצרים logical data gateway, כזה שלא רק מכניס ומוציא מידע ל DB אלא גם מבצע עליו set של פעולות מוכוונות business.
 
למעלה