מצגת 02
הלוגיקה העסקית
BusinessLogicLayer
הישויות, ההגדרות והכלים המשותפים — הכול בלי לדעת שקיים דפדפן.
מה תפקיד השכבה?
- כאן חיות הישויות (Car, Student…) וכללי העסק שלהן.
- יורשת מ-
Recordשל שכבת הנתונים — ולכן כל ישות כבר יודעת להישמר ולהיטען. - אסור לה להכיר UI או HTTP: אין HttpContext, אין HTML, אין Session.
- בזכות זה אותה BLL משרתת אתר, אפליקציית MAUI, Job לילי ובדיקות.
ישות עסקית = מחלקה קטנה
public class Student : Record
{
[Column(Size = 100)] public string FirstName { get; set; }
[Column(Size = 100)] public string LastName { get; set; }
[Column(Size = 20)] public string IdNumber { get; set; }
[Column] public DateTime BirthDate { get; set; }
[Column] public int Grade { get; set; }
[Column] public double Average { get; set; }
[Column] public bool IsActive { get; set; }
[Column(Size = 255)] public string Picture { get; set; }
}
- שדות = עמודות. שום דבר מעבר.
- לוגיקה עסקית (חישוב ממוצע, ולידציה של ת"ז) מתווספת כמתודות על אותה מחלקה.
- קשר לישות אחרת? תכונה מטיפוס הישות — נשמרת אוטומטית כ-
BIGINTשל ה-ID שלה.
Settings — קונפיגורציה שחיה ב-DB
// קריאה (מטמון בזיכרון, נטען פעם אחת בעליית האפליקציה):
string url = Settings.Val["MeshulamUrl"];
// כתיבה:
await Settings.SetAsync("MeshulamUrl", "https://...");
// זריעת ברירות מחדל — כל פרויקט דורס את CreateAsync:
public override async Task CreateAsync()
{
await base.CreateAsync();
await AddAsync("MeshulamUrl", "כתובת סליקה", "https://sandbox...");
}
- למה DB ולא appsettings.json? כי אפשר לשנות בזמן ריצה, לכל לקוח, בלי דיפלוי.
- הזריעה אידמפוטנטית — רצה בכל עלייה, מוסיפה רק מפתחות חסרים.
Util — ארגז הכלים המשותף
- תאריכים:
DateString, ToDate, חודשים עבריים ולועזיים, Decode("תשע\"ו")=776. - ולידציה:
IsValidTz(ספרת ביקורת), IsPhone, IsValidEmail. - טקסט:
StripHTML, CleanHiddenChars, UrlEscape.
- קבצים:
Mime(), ולידציית סיומות, Compress/Decompress(GZip). - אבטחה:
ProtectAppState— הצפנת מצב האפליקציה שנשלח ללקוח. - רשת:
SendHttpRequestAsyncעם HttpClient משותף.
reuse-first: לפני שכותבים עזר חדש — בודקים שהוא לא כבר כאן.
ייצוא מסמכים — עברית כולל
- מחלקת בסיס אחת:
Exporter— מחזירהbyte[]; הקונטרולר עוטף ב-File(...). - Excel (NPOI) — גיליון RTL אמיתי; Word (OpenXML) — טבלאות BiDi.
- PDF (MigraDoc) — פונט מוטמע בקובץ ה-DLL ו-
FlipHebrewשמסדר עברית ויזואלית.
Exporter exporter = new ExcelExporter("Students.xlsx", rtl: true);
exporter.AddTable(dataTable);
return File(exporter.GetBytes(), exporter.ContentType, exporter.FileName);
כללי הזהב של השכבה
- אסינכרוני עד הסוף — מתודה שנוגעת ב-DB מחזירה
Task. - בלי תלות ב-UI — מה שצריך נתוני-סביבה מקבל אותם כפרמטר.
- ישויות רזות; לוגיקה משותפת עולה ל-
Utilאו למחלקת בסיס. -
Settingsל-DB, לא לקבצי קונפיגורציה. - מה שנכון לכל הפרויקטים — מתוקן קודם כאן, בתבנית.