רשימת בדיקה לפני מעבר מ-‎.NET Framework ל-‎.NET

· עודכן בתאריך: · · .NET, .NET Framework, C#, מודרניזציה, פיתוח Windows, מעבר

הורידו את רשימת הבדיקה בגרסת Excel עם גליון יפני ואנגלי

הקובץ הזה בנוי משני גליונות, Checklist-ja ו-Checklist-en, ומרכז את רשימת הבדיקה שלפני התחלת העבודה מ-13 הפרקים ל-7 קטגוריות ו-34 סעיפים: מדיניות / סידור צד ‎.NET Framework הנוכחי / סוג היישום ובחירת טכנולוגיה / טכנולוגיות לא נתמכות ו-API-ים שדורשים תשומת לב / תלות ייעודית ל-Windows / shared library וגישה לנתונים / תפעול ו-build. עמודות Status ו-Notes נשארות ריקות, כך שאפשר להשתמש בקובץ ישירות כטבלת מיפוי לכל פרויקט. כדאי לעבור עליו לפני קריאת המאמר — כך קל יותר לתפוס את זרימת 13 הפרקים.

משנים את TargetFramework ב-.csproj ל-net10.0, מעדכנים כמה חבילות NuGet, וכש-build עובר — סיימנו.

……אם זה היה המעבר, זה היה די שליו. בפועל, בדרך כלל זה לא ככה.

בסביבת ‎.NET Framework בשטח, ישנן לא מעט הנחות יסוד שבדרך כלל לא מודעים אליהן — System.Web,‏ WCF,‏ Web Forms,‏ packages.config ישן,‏ web.config.install.xdt,‏ DLL native,‏ COM / ActiveX, בקרות צד שלישי שרצות רק בזמן עיצוב, הנחה שקטה של x86,‏ ResX תלוי-designer, ו-serializer ישן.

לכן, מה שבאמת חשוב במעבר מ-‎.NET Framework ל-‎.NET הוא המיפוי לפני תחילת המימוש. אם מפרקים את הסוגיות לפני תחילת העבודה, המעבר נהיה לא “הימור גדול” אלא “עבודה שמתקדמת סעיף אחר סעיף”.

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

איור 1: היכולת לפרק סוגיות לפני תחילת העבודה קובעת אם המעבר יהיה הימור או עבודה מסודרת.

המאמר הזה מסכם מה כדאי לבדוק לפני מעבר יישום עסקי קיים ב-‎.NET Framework 4.x ל-‎.NET הנוכחי. היעד העיקרי הוא סוגי היישומים הבאים:

  • ספריות מחלקות
  • יישומי מסוף
  • שירותי Windows
  • WinForms /‏ WPF
  • ‏ASP.NET Framework (‏MVC / Web API / Web Forms)
  • יישומים שמשתמשים ב-WCF
  • יישומים שמשתמשים ב-EF6

זמן הכתיבה הוא 2026-03-15. תקופות התמיכה והמלצות הכלים הרשמיים משתנות עם הזמן, ולכן אם קוראים את המאמר בפער זמן, כדאי לבדוק גם את המידע הרשמי.

1. קודם המסקנה

תחילה, רק את המסקנות שלא כדאי לפספס:

  • קודם מסדרים את צד ‎.NET Framework לפני המעבר. גם במדריך הרשמי של Microsoft ממליצים, לפני ההעברה, לעלות ל-‎.NET Framework 4.7.2 ומעלה, להפוך ל-PackageReference, לעבור לסגנון SDK, ולעדכן תלויות קודם.
  • הקושי נקבע לפי מודל היישום, ולא כמות הקוד. ספריות מחלקות ומסופים יחסית קלים, ואילו ASP.NET Framework,‏ Web Forms, שרת WCF ו-WF‏ (Workflow Foundation) נוטים להיות כבדים.
  • WinForms /‏ WPF יכולים לעבור ל-‎.NET אבל נשארים ייעודיים ל-Windows. טעות בהבנה כאן מובילה למוקש קלאסי — עברו את המעבר אבל היישום עדיין לא רץ על מכולת Linux.
  • המעבר מ-ASP.NET Framework ל-ASP.NET Core הוא בפועל מעבר ארכיטקטורה. ביישום קטן אפשר לפעמים לעבור בבת אחת, אבל במערכת ייצור גדולה בטוח יותר להניח מעבר הדרגתי.
  • WCF ו-EF6 לפעמים אפשר להפריד ממעבר זמן הריצה. ללקוח WCF יש חבילה נתמכת ל-‎.NET, ו-EF6 אפשר להעביר בנפרד ל-EF Core אחרי המעבר ל-‎.NET מודרני.
  • מצד שני, יצירת AppDomain,‏ ‎.NET Remoting,‏ CAS (‏Code Access Security, אבטחת גישה לקוד),‏ COM+,‏ Workflow Foundation, ותלות ב-BinaryFormatter הם תמרורי אזהרה. אם לא מגלים אותם קודם, נפח העבודה מתפוצץ בהמשך.
  • packages.config /‏ install.ps1 /‏ XDT (‏XML Document Transform, מנגנון שהופך web.config וכדומה) / נכסי content / DLL native / COM / ActiveX / הנחת x86 — כל אלה נוטים ליפול בזמן ריצה או בזמן עיצוב גם כש-build עובר, ולכן סורקים אותם לפני תחילת העבודה.
  • נכון ל-2026-03, ‎.NET 10 הוא LTS. נקודת ההגעה למעבר חדש טבעי לחשוב עליה בהתבסס על ה-LTS הנוכחי.
  • מעבר בלי בדיקות, מדידה והכנה ל-rollback הוא מסוכן. המעבר הוא לא בעצם עבודת מימוש, אלא עבודה של חשיפת תנאי היסוד אחד-אחד.

מפת הידע של המאמר

המעבר מ-.NET Framework ל-.NET דורש בדיקת מלאי לפני שמתחילים לממש. המרה ל-PackageReference ‏(היורש של packages.config) ולפרויקט בסגנון SDK היא עבודה שכדאי לסיים לפני המעבר עצמו, לא במסגרתו. יצירת AppDomain חדש, .NET Remoting,‏ COM+ ו-Workflow Foundation אינם תואמים ל-.NET, וגם BinaryFormatter עלול שלא להיות תואם בהתאם לנסיבות. ל-WCF יש מצב שונה בצד הלקוח ובצד השרת — בצד השרת נדרש תכנון מחדש לכיוון CoreWCF או gRPC. ‏ASP.NET Framework הוא היורש של ‏ASP.NET Core, אך Web Forms אינו אותו app model, וכדאי להפריד את המעבר מ-EF6 ל-EF Core מהמעבר של ה-runtime ולדחות אותו למועד מאוחר יותר. ‏WinForms/WPF ניתנים למעבר אך נשארים ייעודיים ל-Windows, והתלות ב-API ייעודי ל-Windows ניתנת להקלה באמצעות חבילת התאימות של Windows.

מפת הידע של רשימת התיוג לפני מעבר מ-.NET Framework ל-.NETתרשים המראה את היחסים בין צורת התלויות, טכנולוגיות שאינן נתמכות, הטיפול ב-WCF וב-EF6, והתלות ב-API ייעודי ל-Windows — כרכיבים שיש לסדר לפני מעבר מ-.NET Framework ל-.NET.מחייביורש אתמשתמש ביורש אתצריך לקדום לצריך לקדום לשימוש לא מומלץ למענה מומלץ למשתמש באינו מתיישב עםאינו מתיישב עםאינו מתיישב עםאינו מתיישב עםאינו מתיישב עםמחייבמחייבמממש אתיורש אתצריך לקדום ליורש אתאינו מתיישב עםאינו מתיישב עםמשתמש במשתמש במשתמש במשתמש במצמצםמשתמש במחייבמחייבמעבר מ-‎.NET Framework ל-‎.NET.NET Framework‏.NET (מ-Core ואילך)‏Windows Compatibility PackPackageReferencepackages.configפרויקט בסגנון SDK.NET Upgrade Assistantמודרניזציה בעזרת GitHub Copilot.NET Standard 2.0יצירת AppDomain.NET RemotingCOM+(System.EnterpriseServices)Workflow FoundationBinaryFormatterשרת WCF‏ (אירוח שירות WCF)CoreWCFgRPCEF CoreEF6(Entity Framework 6)ASP.NET CoreASP.NET Framework(MVC/Web API)ASP.NET Web FormsSystem.Web / HttpContext.CurrentWPFWindows Formsתלות ב-API ייעודי ל-Windowsלקוח WCF

בתרשים, קו מלא מציין קשר שמתקיים תמיד וקו מקווקו מציין קשר מותנה (תנאי ההתקיימות מפורטים בהסבר של כל קשר בעמוד המפורט). רשימת כל הקשרים (סך הכול 30, עם אסמכתה ורמת ודאות) והגדרות המושגים המרכזיים מרוכזות בעמוד המפורט של מפת הידע (ביפנית). נתונים: JSON-LD / Turtle

2. קודם קובעים “האם באמת צריך לעבור עכשיו”

הדבר הראשון שכדאי לקבוע הוא לא “איך לעבור”, אלא האם באמת צריך לעבור את היישום הזה עכשיו.

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

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

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

2.1 גם החלטה להישאר עם ‎.NET Framework היא סבירה לגמרי

‎.NET Framework 4.8.1 ממשיך לקבל תמיכה כל עוד הוא רץ על Windows נתמך. כלומר, זה לא סיפור פשוט של “אם לא נעביר הכול מיד ל-‎.NET מודרני, זה מסוכן”.

עם זאת, יש להישארות מגבלות ברורות.

  • לא ניתן לצאת מ-Windows בלבד
  • ממשיכים לשאת ASP.NET Web Forms או שכבת שרת ישנה
  • קשה ליהנות משיפורי ביצועים, תכונות שפה ומערכת אקולוגית של ‎.NET חדש
  • קל להיסחף מהנחות היסוד העדכניות של ענן, מכולות ו-CI/CD

מצד שני, אם התלות הזו חזקה, הגיוני להישאר בינתיים על ‎.NET Framework 4.8.1 עם תפעול יציב, ולתכנן החלפה בקו נפרד.

הישארות היא בחירה סבירהתרשים המראה שאם יש תלות רגרסית חזקה כמו Web Forms, תאימות שרת WCF או COM+, הגיוני להישאר בינתיים על .NET Framework 4.8.1 עם תפעול יציב, ולתכנן החלפה בקו נפרד.יש תלות רגרסית חזקהבינתיים, תפעול יציב על 4.8.1תכנון החלפה בקו נפרדמגבלות כמו Windows בלבד נשארות

איור 3: כשהתלות עמוקה, שילוב של תפעול יציב על 4.8.1 ותכנון החלפה נפרד הוא ריאלי.

  • יש כמות גדולה של נכסי מסך ב-Web Forms
  • צריך לשמור בקפדנות על תאימות שרת WCF
  • תלות עמוקה ב-Workflow Foundation או ב-COM+
  • רכיב צד שלישי לזמן עיצוב לא נתמך ב-‎.NET מודרני
  • לא ניתן לאשר מבחינה עסקית שינוי אפיון גדול

2.2 מה משתנה לפי כל בחירה

בחירה מה משתפר מה נשאר / מה נאבד מתי מתאים
להישאר עם ‎.NET Framework 4.8.1 קל יותר לשמור על נכסים קיימים ולתפעל ביציבות Windows בלבד, מודל יישום ישן, מגבלת מודרניזציה תלות רגרסית חזקה, כרגע עדיפות עסקית עם תפעול יציב
מעבר ל-‎.NET מודרני, נשארים ב-Windows אפשר להביא לזמן ריצה ושרשרת כלים מודרנית. תועלת גדולה בביצועים, חוויית פיתוח וסגנון SDK תלות ב-API של Windows נשארת. לא הופך לחוצה-פלטפורמות יישום עסקי שמשתמש ב-WinForms /‏ WPF, שירות Windows,‏ API של Windows
מעבר ל-‎.NET מודרני, עם ראייה לעתיד ל-Linux / מכולה / ענן חופש רב יותר במיקום פריסה. קל יותר גם לחדש את מודל התפעול צריך להסיר קודם API-ים ומודל יישום ייעודיים ל-Windows רוצים להעביר את צד השרת לענן, וגם לחדש את התשתית

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

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

איור 4: אם משנים את השאלה מ”רוצים לעבור?” ל”לאן רוצים להגיע?”, האפשרויות מתבררות.

3. ארבע מדיניויות שכדאי לקבוע מראש

3.1 גרסת ‎.NET של נקודת ההגעה

בזמן הכתיבה, לפי מדיניות התמיכה של Microsoft, ‎.NET 10 הוא LTS. מצד שני, ‎.NET 8 LTS ו-‎.NET 9 STS שניהם מתוכננים לסיים תמיכה באותו התאריך, 2026-11-10. הסיבה ש-STS מקבל את אותו תאריך כמו LTS היא שתקופת ה-STS הוארכה מ-18 חודשים ל-24 חודשים. אם סופרים לפי ההנחה הישנה ש”STS זה 18 חודשים”, נראה שסיום התמיכה של ‎.NET 9 הוא ב-2026-05-12, ולכן כשמתבססים על תאריך, כדאי לוודא מול מידע מחזור החיים הרשמי.

לכן, כשעוברים מ-‎.NET Framework מחדש, אלא אם יש נסיבות מיוחדות, טבעי לקבוע את ה-LTS הנוכחי כנקודת ההגעה.

הגישה המעשית כאן פשוטה:

  • למעבר קטן שרוצים לסיים מהר, מגיעים ישירות ל-LTS הנוכחי
  • גם במערכת ליבה עם תפעול ארוך-טווח, חושבים ראשית על ה-LTS הנוכחי
  • “בגלל נוחות ספרייה קיימת רוצים LTS קודם” יכול להיות נסיבה סבירה, אבל בודקים עד מתי היא נתמכת לפי תאריך
הגישה לבחירת גרסת ההגעהתרשים המראה שגם מעבר קטן וגם מערכת ליבה בוחרים בבסיסיות ב-LTS הנוכחי, ואם רוצים LTS קודם בגלל ספרייה קיימת בודקים את תאריך סיום התמיכה.בסיסינוחות ספרייה קיימתבוחרים ‎.NET לנקודת ההגעהמגיעים ל-LTS הנוכחישוקלים גם LTS קודםבודקים תאריך סיום תמיכה ומחליטים

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

3.2 להישאר ייעודי ל-Windows, או לשאוף לחוצה-פלטפורמות בעתיד

ההחלטה הזו משנה משמעותית מה בודקים.

  • אם נשארים ייעודיים ל-Windows, אפשר לנקוט מסלול מעשי של מודרניזציה תחילה של זמן הריצה, בעזרת WPF /‏ WinForms ו-Windows Compatibility Pack.
  • אם שואפים בעתיד גם ל-Linux / הכלה במכולה, צריך למפות מוקדם API-ים שמניחים Windows כמו System.Drawing.Common, רישום המערכת,‏ WMI,‏ EventLog, שירות Windows ו-Office Interop.

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

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

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

3.3 לעשות הכול בבת אחת, או מעבר הדרגתי

יש שלושה סוגים עיקריים למעבר:

  • מעבר מרוכז שקרוב ל-in-place
  • מעבר שבו ישן וחדש רצים side-by-side זה לצד זה
  • מעבר הדרגתי שמתקדם בהדרגה לפי route / ספרייה

בפרט, ביישומי ASP.NET Framework, גם המדריך של Microsoft מנחה בבירור ל-incremental migration. אם לא רוצים לעצור את הייצור, יש הרבה תכונות, והתלויות סביב רבות, טבעי יותר לתכנן מראש מתוך הנחת מעבר הדרגתי.

שלושת הסוגים של המעברתרשים המראה שיש שלושה סוגי מעבר - מרוכז קרוב ל-in-place, side-by-side עם ישן וחדש במקביל, ומעבר הדרגתי לפי route או ספרייה - ובתנאי שלא רוצים לעצור את הייצור, ההדרגתי טבעי יותר.בוחרים סוג מעברמעבר מרוכז (קרוב ל-in-place)side-by-side עם ישן וחדש במקבילמעבר הדרגתי לפי route / ספרייהאם לא רוצים לעצור ייצור, זו ההנחה הטבעית

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

3.4 מה “מוציאים מהיקף המעבר הזה”

מעבר נוטה להיכשל כי לוקחים על עצמם יותר מדי.

לדוגמה, לעשות בו-זמנית את הבאים נוטה להיות כבד:

  • ‎.NET Framework → ‎.NET
  • ASP.NET Framework → ASP.NET Core
  • EF6 → EF Core
  • שרת Windows → מכולת Linux
  • שינוי תשתית אימות
  • שינוי תשתית לוגים / ניטור
  • מעבר מסד נתונים

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

בפועל, ההפרדה הבאה עובדת יותר טוב:

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

איור 8: בלי לעשות הכול בו-זמנית, אלא בהפרדה של זמן ריצה, מודל היישום והשוליים, המעבר לא נהיה כבד.

4. הבסיס שמכינים לפני תחילת העבודה

המדריך המקדים למעבר של Microsoft מעשי מאוד. בקיצור, מדובר בהכנת פרויקט ‎.NET Framework הנוכחי לכיוון כניסה מודרנית לפני המעבר.

4.1 עלייה ל-‎.NET Framework 4.7.2 ומעלה

במדריך הרשמי מומלץ, לפני ההעברה, לכוון ל-‎.NET Framework 4.7.2 ומעלה. הסיבה היא שגם כש-.NET Standard לא מחזיק ישירות את ה-API הקיים, קל יותר להתקרב לחלופת API עדכנית יותר.

בעבודה מעשית, אם אפשר, ברור יותר לחשוב מנקודת מוצא של 4.8.1.

  • ברור יותר מבחינת נקודת מבט התמיכה
  • קל יותר להתייחס לזה כנקודת יציבות אחרונה בצד ‎.NET Framework
  • קל יותר לגבש מדיניות של “קודם מסדרים בצד ה-Framework הנוכחי”

מה משתנה אם עושים את זה קודם

  • קל יותר לייצב את הטיפול בספריות משותפות של .NET Standard 2.0
  • אפשר לצמצם מראש רעש שמקורו בזמן ריצה ישן
  • קל יותר להבחין אם מקור בעיית תאימות הוא “ה-Framework הישן” או “ההפיכה ל-‎.NET מודרני”

4.2 מעבר ל-PackageReference

במדריך המקדים מומלץ להתקדם צורת ההפניה ל-PackageReference. אם עושים את זה קודם, התצוגה הכוללת של ניהול התלויות משתפרת משמעותית.

מה משתנה כשעוברים ל-PackageReference

  • הפניות החבילות מרוכזות ב-csproj
  • קל יותר לראות תלויות טרנזיטיביות
  • הנחת ה-restore מתאימה לצד ‎.NET מודרני
  • תאימות טובה יותר עם CLI /‏ CI

עם זאת, יש כאן מוקש.

המוקש הטיפוסי

בתיעוד הרשמי של NuGet כתובות המגבלות הבאות במעבר מ-packages.config ל-PackageReference:

  • פונקציית ההמרה המובנית של Visual Studio לא זמינה בפרויקטי ASP.NET
  • חבילות שתלויות ב-install.ps1 /‏ uninstall.ps1 עלולות לא לפעול כצפוי
  • נכסים בתיקיית content עלולים להיות מתעלמים
  • המרות XDT כמו web.config.install.xdt לא מוחלות
  • חבילות עם מבנה assembly ישן תחת lib עלולות לא להסתדר כראוי

כלומר, לא כדאי לחשוב שמדובר רק בשינוי צורת החבילה. בפרט, ל-classic ASP.NET הייתה תרבות משמעותית שבה התקנת חבילת NuGet כותבת מחדש את web.config, ולכן בזמן המעבר קל שהנחות סמויות יעלו לפני השטח.

הנחות סמויות שנחשפות עם ההפיכה ל-PackageReferenceתרשים המראה שבמעבר מ-packages.config ל-PackageReference, install.ps1 והמרות XDT ונכסי content עלולים לא להיות מוחלים, ולכן הנחות סמויות שהתבססו על כתיבה מחדש של web.config בזמן התקנה נחשפות.הפיכה ל-PackageReferenceinstall.ps1 עלול לא לפעולהמרות XDT לא מוחלותנכסי content עלולים להתעלםההנחות הסמויות נחשפות

איור 9: גם אם חושבים שזו רק המרת צורה, ההסתמכות על מנגנוני ההתקנה נחשפת בבת אחת.

באילו כלים ממירים

זה לא רק עבודה ידנית. עם זאת, לכל כלי טווח שונה.

כלי מה אפשר לעשות הנחות והערות
פונקציית ההמרה של Visual Studio בסייר הפתרונות, לחיצה ימנית על “הפניות” או על packages.config ובחירה ב-Migrate packages.config to PackageReference... מבצעת המרה Visual Studio 2017 15.7 ומעלה. לא זמין בפרויקטי ASP.NET ו-C++. אם לא מופיע בתפריט, פותחים פעם את שחזור ה-NuGet או את מנהל החבילות ואז לוחצים ימנית שוב
‏.NET Upgrade Assistant מבצע ניתוח ושדרוג של הפרויקט יחד בתיעוד הרשמי הוא כבר לא מומלץ, ומופנים להשתמש במודרניזציה בעזרת GitHub Copilot
מודרניזציה בעזרת GitHub Copilot מסייע עד להערכה, תכנון, תיקון קוד ואימות ליבת ההנחיה הרשמית הנוכחית. כפי שבפרק 4.5, מניח Visual Studio,‏ Copilot וקוד C#
הפיכה לסגנון SDK ידנית יוצרים csproj חדש ומעבירים רק את הפריטים הנדרשים בפרויקט עם מעט קבצים, לעיתים זה המהיר ביותר

פונקציית ההמרה של Visual Studio יוצרת גיבוי של הפרויקט לפני ההרצה, ומוציאה בסוף דוח המרה (תלויות ברמה עליונה, תלויות טרנזיטיביות, בעיות תאימות שזוהו). בתיעוד כתוב שאם רוצים לחזור אחורה, משחזרים את csproj ואת packages.config מתיקיית הגיבוי, ומריצים update-package -reinstall במסוף מנהל החבילות.

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

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

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

4.3 מעבר לסגנון SDK

במדריך המקדים מומלצת גם המרה לצורת פרויקט בסגנון SDK.

זה משפיע משמעותית.

מה משתנה עם סגנון SDK

  • ה-csproj נעשה פשוט משמעותית
  • תאימות טובה עם PackageReference
  • קל יותר לבצע multi-targeting
  • קל יותר להתאים ל-CI/CD שמתבסס על dotnet build /‏ dotnet test /‏ dotnet publish
  • הקרבה למבנה של צד ‎.NET מודרני מצמצמת את ההפרש בשלב השני

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

מעבר לסגנון SDK מצמצם הפרשתרשים המראה שקפיצה ישירה ל-.NET מודרני עם csproj ישן וניהול NuGet ישן יוצרת הפרש גדול מדי, ואילו מעבר קודם לסגנון SDK מקרב למבנה הצד המודרני ומצמצם את ההפרש בהמשך.קפיצה ישירהקודם מעבר לסגנון SDKcsproj ישן + ניהול NuGet ישןהפרש גדול מדיהתקרבות למבנה הצד המודרניהפרש בהמשך מצטמצם

איור 11: אם משלבים מעבר לסגנון SDK, ההפרש בקפיצה ל-‎.NET מודרני מצטמצם.

4.4 עדכון תלויות קודם

גם זה לפי המדריך הרשמי, אבל את התלויות מקדמים להגרסה העדכנית הזמינה, ואם אפשר, לגרסה שתומכת ב-‎.NET Standard.

המשמעות בעשיית זה קודם

  • מהר יותר יודעים “האם החבילה הזו אפשר להשתמש בה ב-‎.NET מודרני”
  • מונעים מתלויות ישנות להפוך לרעש
  • קל יותר להפוך shared library ל-netstandard2.0
  • קל יותר לרכז את עבודת המעבר בשלב הבא ב”העברת הקוד”
המשמעות בעדכון התלויות קודםתרשים המראה שעדכון התלויות מראש לגרסה עדכנית מאפשר לדעת מהר אם הן תומכות ב-.NET מודרני, מפחית רעש מתלויות ישנות, ומאפשר לרכז את עבודת המעבר בשלב הבא בהעברת הקוד.עדכון התלויות מראשמהר יותר יודעים אם תומך ב-.NET מודרנימפחית רעש מתלויות ישנותהשלב הבא מתמקד בהעברת הקוד

איור 12: ככל שעדכון התלויות מוקדם יותר, גוף המעבר יכול להתמקד בהעברה עצמה.

4.5 בודקים גם את הנחות הכלים הרשמיים

נכון ל-2026-03, מרכז הכובד של הנחיית Microsoft עבר לכיוון מודרניזציה בעזרת GitHub Copilot. במקום להתבסס רק על כלי מעבר ותיקים, מעשי יותר להתייחס לזה כזרם תמיכה שכולל הערכה, תכנון, תיקון קוד ואימות.

עם זאת, בתיעוד הנוכחי, ההנחה היא Visual Studio 2026 או Visual Studio 2022 בגרסה נתמכת,‏ GitHub Copilot, וגם קוד C#.

למה הבדיקה הזו נדרשת

  • מה אפשר לצפות מהכלי הרשמי משתנה
  • קל יותר להתאים בין הצוות את הנחות ה-IDE /‏ build agent / התוספים
  • אפשר להגיע להחלטה שלא לצפות ליותר מדי אוטומציה בפתרונות VB.NET

לא נדיר לראות סביבת עבודה שיש בה גם VB.NET. לכן, שווה לבדוק מראש “עד כמה הכלי הרשמי העדכני יעזור”.

המצב הנוכחי וההנחות של הכלים הרשמייםתרשים המראה ש-.NET Upgrade Assistant נהיה לא מומלץ ומרכז הכובד של ההנחיה עבר למודרניזציה בעזרת GitHub Copilot, אבל ההנחה היא Visual Studio, Copilot וקוד C#, ולכן בסביבה עם VB.NET לא כדאי לצפות ליותר מדי אוטומציה.לא מומלץ, מפנה לאם יש VB.NET.NET Upgrade Assistantמודרניזציה בעזרת GitHub Copilotהנחה: Visual Studio + Copilot + C#לא לצפות ליותר מדי אוטומציה

איור 13: מרכז הכובד של הכלים עבר למודרניזציה בעזרת Copilot, וסביבה שלא תואמת את ההנחות שלו דורשת התייחסות נפרדת.

5. אומדים את הקושי לפי סוג הפרויקט

נוטים לדבר על המעבר מ-‎.NET Framework ל-‎.NET כעל דבר אחד, אבל בפועל כל סוג פרויקט הוא משחק בפני עצמו.

5.1 תחושת קושי גסה

סוג תחושת קושי הנקודות המרכזיות
ספריית מחלקות נמוך〜בינוני תאימות API, תלויות, חלוקת יעד
מסוף / batch / חלק משירותי Windows נמוך〜בינוני שיטת הפצה, תלות native, תצורה
WinForms /‏ WPF בינוני נשאר ייעודי ל-Windows, designer, UI צד שלישי, סביבת BinaryFormatter
ASP.NET MVC /‏ Web API בינוני〜גבוה מעבר מודל יישום ל-ASP.NET Core, אימות, session, תצורה,‏ DI
ASP.NET Web Forms גבוה הפרש גדול במודל המסך, הנחת החלפת שכבת UI
לקוח WCF בינוני החלפת חבילה, חוזה, תצורה
שרת WCF גבוה CoreWCF או תכנון מחדש עם gRPC / HTTP API
ביצוע בו-זמני של EF6 → EF Core גבוה ORM שונה לגמרי, הבדל התנהגות, היסטוריית מעברים

5.2 המפתח בספריית מחלקות הוא איך חותכים את “הגבול המשותף”

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

תלויות מהסוג הבא מעלות את הקושי:

  • נוגעים ב-System.Web
  • מסתכלים ישירות ב-HttpContext.Current
  • כוללים סוגי WPF /‏ WinForms ב-API הציבורי
  • נשענים יתר על המידה על API-ים של Windows כמו רישום המערכת,‏ WMI,‏ EventLog
  • תלויים ב-AppDomain או ב-Remoting

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

איך רואים את כובד ספריית המחלקותתרשים המראה שספרייה שבה אפשר להוציא רק את לוגיקת העסק קלה למעבר, ואילו ספרייה שנושאת גם מודל יישום דרך System.Web, סוגי UI, API של Windows ו-AppDomain כבדה.אפשר להוציא רק לוגיקהנושאת מודל יישוםבוחנים ספריית מחלקותמעבר קלמעבר כבדתלות ב-System.Web, סוגי UI, API של Windows וכדומה

איור 14: הקושי של הספרייה נקבע לא לפי מספר השורות, אלא לפי כמות מודל היישום שהיא נושאת.

5.3 WinForms /‏ WPF קלים למעבר, אבל נשארים ייעודיים ל-Windows

WinForms ו-WPF יכולים לעבור ל-‎.NET. עם זאת, שניהם נשארים תשתיות ייעודיות ל-Windows.

טעות בציפייה כאן מסוכנת.

  • מה שמשתפר
    • עולים על זמן ריצה, שפה וסגנון SDK של ‎.NET מודרני
    • קל יותר להתאים CI/CD וניהול חבילות לימינו
    • זוכים לחלק משיפורי הביצועים והתחזוקה
  • מה שלא משתנה
    • היות ייעודי ל-Windows
    • נשארות בעיות תאימות של בקרות UI ורכיבים לזמן עיצוב
    • בעיות ActiveX /‏ COM / DLL native לא נעלמות

בנוסף, יש מקרים שבהם WinForms /‏ WPF דורשים בדיקת השפעת BinaryFormatter. בפרט, כשקשור ל-clipboard,‏ drag & drop,‏ ResX, וסריאליזציה בזמן עיצוב עם custom type, זה נוטה לצוף כשמעלים את היעד ל-‎.NET 9 ומעלה.

הציפייה למעבר WinForms / WPFתרשים המראה ש-WinForms ו-WPF יכולים לעבור ל-.NET ולעלות על הזרימה של הזמן ריצה, השפה והסגנון המודרני, אבל נשארים ייעודיים ל-Windows, וגם נדרשת לפעמים בדיקת BinaryFormatter.מעבר WinForms / WPFעולים על ההטבות של .NET מודרנינשארים ייעודיים ל-Windowsנדרשת לפעמים בדיקת BinaryFormatter

איור 15: ה-UI השולחני יכול לעבור, אבל התכונה של להיות ייעודי ל-Windows ממשיכה איתו.

5.4 ASP.NET Framework זה לא “מעבר זמן ריצה” אלא “מעבר מודל יישום”

המעבר מ-ASP.NET Framework ל-ASP.NET Core מוגדר גם במדריך של Microsoft כ-non-trivial. זה לא רק כי שמות ה-API משתנים, אלא כי הארכיטקטורה שמונחת ביסוד שונה.

המקומות שבהם ההבדל בולט הם בערך אלה:

  • מודל האירוח (Hosting)
  • צינור ה-middleware
  • מודל עיבוד הבקשות
  • Session /‏ Cache
  • אימות / הרשאה
  • תצורה
  • הזרקת תלויות (DI)
  • לוגים / ניטור

מה שכדאי לבדוק קודם ביישום ASP.NET Framework הוא בערך אלה:

  • מאיזה route / endpoint אפשר להעביר קודם
  • האם אפשר להסיר תלות ב-System.Web מ-shared library
  • איך מתאימים אימות / session / טיפול בחריגות / לוגים
  • האם עוברים בהדרגה בלי לעצור את הייצור

בפרט, ביישום גדול, מעשי יותר לתכנן מראש בהנחת incremental migration.

מעבר ASP.NET הוא מעבר מודל יישוםתרשים המראה שהמעבר מ-ASP.NET Framework ל-Core הוא לא החלפת שמות API אלא מעבר מודל יישום עם שינוי בארכיטקטורה שביסוד - hosting, middleware, אימות, תצורה, DI - ושביישום גדול מעשי יותר להניח מעבר הדרגתי.ביישום גדולASP.NET Framework → Coreהארכיטקטורה שביסוד משתנהhosting, middleware, אימות, תצורה, DIתכנון בהנחת incremental migration

איור 16: המעבר ב-ASP.NET הוא לא מעבר זמן ריצה אלא מעבר מודל יישום, וככל שההיקף גדול, ההנחה ההדרגתית טבעית יותר.

5.5 Web Forms נכנסים דרך “פירוק אחריות” ולא דרך “מעבר נכסים”

Web Forms לא באותו מודל יישום כמו ASP.NET Core. לכן, באומדן, בטוח יותר לא להניח שאפשר להעביר את נכסי המסך כמו שהם.

בעבודה מעשית, לרוב מתחילים מהפירוק הבא:

  • הפרדה בין לוגיקת מסך ללוגיקת עסק
  • פירוק האחריות שקבורה ב-Page /‏ UserControl /‏ ViewState
  • הוצאת לוגיקה עסקית וגישה לנתונים ל-shared library
  • הרכבה מחדש של ה-UI במודל אחר כמו Razor Pages /‏ MVC /‏ Blazor

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

Web Forms נכנסים דרך פירוק אחריותתרשים המראה ש-Web Forms אינם באותו מודל יישום כמו ASP.NET Core, ולכן מפרידים בין לוגיקת מסך לעסק, מוציאים לוגיקה ל-shared library, ומרכיבים מחדש את ה-UI במודל אחר.הנחה של העברה כמו שזהנכסי המסך של Web Formsהפרדה בין לוגיקת מסך ללוגיקה עסקיתהוצאת הלוגיקה ל-shared libraryהרכבה מחדש של ה-UI במודל אחרהאומדן קורס

איור 17: מסתכלים על Web Forms לא כמעבר נכסים אלא כפירוק אחריות ואז הרכבה מחדש במודל אחר.

5.6 מפרידים בין חשיבה על לקוח WCF לשרת WCF

כאן בטוח יותר לא לכרוך יחד.

לקוח WCF

ל-WCF Client יש חבילת NuGet נתמכת ל-‎.NET מודרני. לכן, יש מקרים שבהם אם רק קוראים ל-WCF, זה לא כבד כמו שנראה.

שרת WCF

מצד שני, צד המארח של שירות WCF שונה. במדריך של Microsoft מנחים בעיקר בשני מסלולים לצורך מודרניזציה:

  • כיוון של שימוש ב-CoreWCF לשמירת תאימות ללקוחות קיימים
  • כיוון של מעבר ל-RPC / HTTP מודרני כמו gRPC

עם זאת, CoreWCF לא מביא את כל WCF כמו שהוא — זו תת-קבוצה. מתאים לשמירת תאימות ללקוחות קיימים, אבל שינוי קוד ובדיקה הם הנחת יסוד.

WCF מוערך בנפרד ללקוח ולשרתתרשים המראה שללקוח WCF יש חבילה נתמכת ל-.NET מודרני ולעיתים זה לא כבד כמו שנראה, ואילו בצד השרת צריך לבחור מסלול - שמירת תאימות עם CoreWCF, שהוא תת-קבוצה, או תכנון מחדש עם gRPC.לקוחשרתשמירת תאימותתכנון מחדשבאיזה צד משתמשים ב-WCFמעבר עם חבילה נתמכתבוחרים מסלולCoreWCF (תת-קבוצה)gRPC / HTTP API

איור 18: לצד הקורא ולצד המארח יש קושי ואפשרויות שונים, ולכן לא אומדים אותם יחד.

6. סורקים טכנולוגיות שלא ניתן להשתמש בהן ב-‎.NET, או שקל להיתקע בהן כמו שהן

זו נקודה שחייבים לבצע לפני תחילת העבודה. ל-Microsoft יש רשימה של טכנולוגיות שהיו זמינות ב-‎.NET Framework אבל לא זמינות ב-‎.NET 6 ומעלה.

6.1 טכנולוגיות שנוטות להיות תמרור אזהרה

טכנולוגיה המצב ב-‎.NET איך לחשוב על זה
AppDomain.CreateDomain וכדומה — יצירת AppDomain לא נתמך חושבים על בידוד דרך תהליך נפרד / מכולה /‏ AssemblyLoadContext
‏.NET Remoting לא נתמך תכנון מחדש ל-IPC,‏ HTTP,‏ gRPC,‏ Socket,‏ Pipe וכדומה
CAS / Security Transparency לא נתמך כגבול אבטחה חושבים על מערכת ההפעלה / מכולה / הפרדת הרשאות
System.EnterpriseServices (‏COM+) לא נתמך מפרידים או מחליפים את התכנון שמניח COM+
Workflow Foundation לא נתמך חושבים באומדן נפרד, כולל חלופות כמו CoreWF
שרת WCF לא built-in כמו שהוא בוחרים בין CoreWCF ל-gRPC
BinaryFormatter מ-‎.NET 9 ואילך, המימוש תמיד זורק חריגה מעבר לסריאלייזר אחר, ביקורת ResX / clipboard / drag & drop

6.2 AppDomain הוא “גם אם חלק מה-API נשאר, היצירה עניין נפרד”

סביבת AppDomain קצת מסובכת. גם ב-‎.NET, חלק ממשטח ה-API נשאר, אבל השימוש של יצירת AppDomain חדש ובידוד בו לא נתמך.

לכן, אם השתמשו ב-AppDomain לצרכים הבאים, נדרש תכנון מחדש:

  • בידוד plugin
  • ביטול טעינה דינמית
  • בידוד קוד באמון חלקי
  • הפרדת סביבת הרצה זמנית

מה שכדאי לבדוק לפני המעבר הוא לא רק האם המילה AppDomain מופיעה, אלא לשם מה השתמשו ב-AppDomain.

השימוש ב-AppDomain קובע את ההחלטהתרשים המראה שלמרות שחלק מה-API נשאר, השימוש ביצירת AppDomain חדש ובידוד בו לא נתמך, ולכן מבחינים בין שימוש בסוג בלבד לבין בידוד בפועל, ולבידוד נדרש תכנון מחדש בתהליך נפרד או AssemblyLoadContext.רק שימוש בסוג או במידעיצירה ובידודAppDomain מופיעברוב המקרים אפשר להמשיך כמו שזהנדרש תכנון מחדשתהליך נפרד / מכולה / AssemblyLoadContext

איור 19: לא לפי הימצאות המילה אלא לפי “לשם מה השתמשו בזה” נקבע אם נדרש תכנון מחדש.

6.3 Remoting “עמוק ממה שנראה”

מלבד Remoting עצמו, גם delegate אסינכרוני כמו קריאה ל-BeginInvoke() /‏ EndInvoke() עלול להיכנס להיקף ההשפעה. זה לא Remoting עצמו, אבל הוא לא נתמך ב-‎.NET מודרני, ולכן צריך למפות אותו לפני המעבר.

לכן, בעת החיפוש, בטוח יותר לבדוק גם אלה יחד:

  • System.Runtime.Remoting
  • MarshalByRefObject
  • RealProxy
  • BeginInvoke( /‏ EndInvoke(

6.4 BinaryFormatter צף לפתע לפי target version

BinaryFormatter, ככל שבסיס הקוד ישן יותר, נוטה להשתמש בו “בלי מודעות”.

  • נתונים שנשמרים
  • מטמון
  • שמירת session
  • מצב plugin
  • clipboard / drag & drop
  • ResX
  • סביבת ה-designer של WinForms /‏ WPF

מ-‎.NET 9 ואילך, BinaryFormatter לא כולל מימוש בזמן הריצה, וה-API תמיד זורק PlatformNotSupportedException. כלומר, זה לא נושא ל”נחשוב על זה אחר כך”, אלא נקודה שדורשת ביקורת מוקדמת ברגע שקובעים את ה-target version.

המסלול שבו BinaryFormatter צףתרשים המראה ש-BinaryFormatter נוטה להיות בשימוש בלי מודעות דרך נתונים שנשמרים, ResX וכדומה, ומ-.NET 9 ואילך ה-API זורק תמיד חריגה, ולכן זו נקודה שדורשת ביקורת מוקדמת ברגע שקובעים את ה-target version.שימוש בלי מודעות (ResX, clipboard וכדומה)קביעת target ל-.NET 9 ואילךה-API תמיד זורק חריגהדורש ביקורת מוקדמת ברגע ההחלטה

איור 20: BinaryFormatter משפיע ברגע שקובעים את ה-target, ולכן לא דוחים אותו — מבצעים ביקורת מוקדמת.

6.5 מונחי חיפוש שכדאי לבצע grep עליהם קודם

עוד לפני תחילת העבודה, חיפוש הפתרון כולו לפי המונחים הבאים כבר משנה משמעותית את התמונה.

System.Web
HttpContext.Current
System.Runtime.Remoting
MarshalByRefObject
AppDomain
BinaryFormatter
ServiceHost
ChannelFactory
System.EnterpriseServices
Workflow
packages.config
web.config.install.xdt
install.ps1
DllImport
AxInterop
Microsoft.Office.Interop

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

פקודת החיפוש בפועל

הכלי יכול להיות rg (‏ripgrep) או PowerShell.

# PowerShell. חיפוש מרוכז בכל הפתרון
Get-ChildItem -Recurse -Include *.cs,*.vb,*.config,*.csproj,*.vbproj |
    Select-String -Pattern 'BinaryFormatter|System\.Runtime\.Remoting|MarshalByRefObject|AppDomain\.CreateDomain' |
    Select-Object Path, LineNumber, Line
# ripgrep. כשרוצים קודם לקבל תחושה לפי מספר התוצאות
rg -n --stats "BinaryFormatter|System\.Runtime\.Remoting|AppDomain\.CreateDomain" --glob "*.cs" --glob "*.vb"

מה עושים אחרי שנמצא

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

מונח שנמצא מה בודקים אחר כך הפתרון
System.Web /‏ HttpContext.Current האם אפשר להוציא את זה מחוץ ל-shared library. האם צד הקריאה יכול לארוז ל-DTO הסרה עם האסטרטגיה בפרק 8.5
System.Runtime.Remoting /‏ MarshalByRefObject /‏ BeginInvoke לשם מה נועדה קריאת ה-remote. בין תהליכים, בין מכונות, או רק קריאה אסינכרונית פשוטה תכנון מחדש עם IPC,‏ HTTP,‏ gRPC, מבוסס Task
AppDomain האם משתמשים רק בשם הטיפוס, או מבודדים עם CreateDomain אם המטרה בידוד, תהליך נפרד או AssemblyLoadContext (6.2)
BinaryFormatter האם צריך לקרוא אחר כך את הנתונים שנכתבו. האם משתמשים בזה בעקיפין דרך ResX או clipboard מעבר לסריאלייזר אחר, ותכנון לקריאה מחדש של הנתונים הקיימים (6.4)
ServiceHost /‏ ChannelFactory צד המארח או צד הלקוח הערכה נפרדת לפי 5.6
packages.config /‏ install.ps1 /‏ web.config.install.xdt מה נכתב מחדש בזמן ההתקנה המוקש מ-4.2. מחזיקים את ההגדרה מפורשות
DllImport /‏ AxInterop /‏ Microsoft.Office.Interop הנחת מספר הביטים וכל קובצי הריצה הנדרשים בדיקת bitness בפרק 9.4

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

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

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

7. קובעים עד כמה מקבלים הנחת יסוד ייעודית ל-Windows

טעות נפוצה במעבר היא “אם עברנו ל-‎.NET, זה נהיה חוצה-פלטפורמות”. אין קסם כזה. אם היישום קשור עמוק ל-Windows, גם אחרי המעבר הוא נשאר ייעודי ל-Windows כרגיל.

7.1 להישאר ייעודיים ל-Windows במעבר הוא ריאלי לגמרי

ל-Microsoft יש Windows Compatibility Pack, שמאפשר לגשת מ-‎.NET מודרני להרבה API-ים של Windows כמו רישום המערכת,‏ WMI,‏ EventLog, שירות Windows ו-Directory Services.

הקיום שלו משמעותי בעבודה מעשית.

  • רוצים קודם לעבור ל-‎.NET מודרני
  • אבל בינתיים לא יוצאים מ-Windows
  • אז רוצים לקבל בינתיים את תלות ה-API של Windows

בסביבה כזו, זו אפשרות חזקה.

המטרה הראשונה של המעבר לא חייבת להיות הפיכה לחוצה-פלטפורמות.

7.2 עם זאת, גם API ייעודי ל-Windows הוא “חוב שישפיע בהמשך”

עצם קיומו של Windows Compatibility Pack לא אומר שהכול בטוח.

  • רוצים להכניס למכולת Linux
  • רוצים להריץ בהנחת Kubernetes
  • גם מפתחי macOS / Linux רוצים להריץ את אותו build
  • בעתיד, רוצים להפחית מכונות Windows וירטואליות בענן

אם יש מטרות כאלה, בטוח יותר לחשוף כבר עכשיו את תלות ה-API של Windows.

מקום השימוש בחבילת התאימות והחוב שמאחוריהתרשים המראה שאם בינתיים נשארים על Windows, חבילת התאימות מאפשרת לקבל בינתיים את תלות ה-API של Windows ולעבור ל-.NET מודרני, אבל אם שואפים בעתיד למכולה או ענן, התלות היא חוב שישפיע בהמשך ולכן חושפים אותו כבר עכשיו.בינתיים נשארים על Windowsאם שואפים בעתיד למכולה / ענןרוצים קודם לעבור ל-.NET מודרניחבילת התאימות מקבלת בינתיים את התלותהתלות היא חוב שישפיע בהמשךחושפים אותו כבר עכשיו

איור 22: חבילת התאימות היא גשר ריאלי, אבל התלות שלה עלולה להיות חוב לפי המטרה, ולכן חושפים אותה מראש.

7.3 ‏System.Drawing.Common קל במיוחד לטעות בהבנתו

System.Drawing.Common הוא, מ-‎.NET 6 ואילך, ספרייה ייעודית ל-Windows. אם יש קוד שמשתמש בעיבוד תמונות או ציור טקסט, צריך לקבוע קודם באיזה כיוון הולכים.

  • ממשיכים לתפעל על Windows
  • בעתיד רוצים להריץ גם על Linux / macOS

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

ההסתעפות של System.Drawing.Commonתרשים המראה ש-System.Drawing.Common ייעודי ל-Windows מ-.NET 6 ואילך, ולכן אם ממשיכים על Windows אפשר להישאר כמו שזה בינתיים, ואם רוצים להריץ גם על Linux או macOS צריך לכלול מראש החלפה כמו SkiaSharp או ImageSharp.ממשיכים על Windowsרוצים גם Linux / macOSמשתמשים ב-System.Drawing.Commonאפשר להישאר כמו שזה בינתייםהחלפה ל-SkiaSharp / ImageSharpכוללים זאת מראש בתכנון המעבר

איור 23: מכיוון ש-System.Drawing.Common ייעודי ל-Windows, אופן הטיפול בו נחלק כבר בהתחלה לפי נקודת ההגעה.

7.4 סימנים ייצוגיים לקיבוע ל-Windows

כשיש הפניות או API-ים מהסוג הבא, בטוח יותר לאמוד “לפחות בהתחלה נשארים ייעודיים ל-Windows”.

  • Microsoft.Win32.Registry
  • System.Management
  • System.Diagnostics.EventLog
  • System.ServiceProcess
  • System.DirectoryServices
  • System.Drawing
  • DllImport /‏ P/Invoke
  • הפניית COM
  • AxInterop.*
  • Microsoft.Office.Interop.*

8. אופן הוצאת הספרייה המשותפת קובע את הקושי

בפתרון גדול, אין הגזמה לומר שהצלחת המעבר נקבעת לפי אופן חיתוך ה-shared library.

8.1 קודם מסווגים

נוח יותר לסווג ספריות לשלושה סוגים עיקריים:

  1. לוגיקה עסקית / דומיין טהורה
  2. שכבת ביניים שתלויה מעט במודל היישום
  3. שכבה שצמודה ל-UI /‏ Web / API של Windows

מבין אלה, מה שכדאי להעביר קודם הוא 1.

  • חישוב
  • הכרעת חוקים
  • DTO / חוזה
  • שירות דומיין
  • המרת נתונים פשוטה

אם מוציאים את זה נקי, הקושי הכולל יורד בבת אחת.

שלוש הקטגוריות של הספריות וסדר ההעברהתרשים המראה שמחלקים ספריות ללוגיקה עסקית טהורה, שכבת ביניים תלויית מודל יישום, ושכבה צמודה ל-UI ול-API של Windows, ושמה שכדאי להעביר קודם הוא הלוגיקה העסקית הטהורה.מעבירים ראשונהאחריהאחרונהלוגיקה עסקית טהורהאם מוציאים נקי, הקושי יורדשכבת ביניים תלויית מודל יישוםשכבה צמודה ל-UI / API של Windows

איור 24: מחלקים את הספריות לשלוש שכבות, ומצילים בהדרגה מהלוגיקה הטהורה.

8.2 ‏netstandard2.0 הוא עדיין גשר תקף

לפי ההנחיה של Microsoft, אם יש shared library שצריכה להתקיים גם בצד ‎.NET Framework, הבסיס הוא לחשוב קודם על ‎.NET Standard 2.0`.

חשוב כאן שתי נקודות:

  • ‎.NET Framework לא תומך ב-.NET Standard 2.1
  • אם רוצים להפנות ל-shared library גם מהישן וגם מהחדש, 2.0 הוא הפתרון המעשי ברוב המקרים
הגשר בשם netstandard2.0תרשים המראה ש-.NET Framework לא תומך ב-.NET Standard 2.1, ולכן אם רוצים להפנות ל-shared library גם מהישן וגם מהחדש, .NET Standard 2.0 הוא הפתרון המעשי.יכול להפנותיכול להפנותFramework לא תומךצד ‎.NET Frameworkshared library ב-netstandard2.0צד ‎.NET מודרניnetstandard2.1

איור 25: כגשר שנגיש גם מהישן וגם מהחדש, הפתרון המעשי הוא 2.0 ולא 2.1.

8.3 מה משתנה כשעוברים ל-netstandard2.0

מדיניות מה משתנה מתי מתאים הערה
הפיכה ל-netstandard2.0 קל להפנות גם מהישן וגם מהחדש לוגיקה עסקית טהורה, חוזה משותף, כלי עזר לא ניתן לטעון API ייחודי למודל יישום
multi-target (למשל: net48;net10.0) שומרים על קוד משותף ובכל זאת מחזיקים הפרש לפי סביבה ספרייה עם הפרש קטן בין סביבות מוסיף התניות וניהול build
הפיכה ישירה ל-net10.0 בלבד הכי נקי בעתיד שכבה חדשה שלא צריכה תלות בין ישן לחדש לא ניתן להפניה מ-‎.NET Framework

8.4 מצב תאימות אינו כל-יכול

ל-‎.NET Standard 2.0 יש מצב תאימות שמאפשר להפנות לספריות ‎.NET Framework. עם זאת, זה לא קסם שגורם לכול לפעול באופן שקוף.

לדוגמה, ספרייה שמניחה API ייחודי למודל יישום כמו WPF קשה כרגיל. כלומר, גם אם אומרים shared library, חשוב להצר רק לאחריות שבאמת ניתנת לשיתוף.

8.5 בספריות מסוג ASP.NET, המפתח הוא האם אפשר להסיר את System.Web

כשמבצעים מעבר הדרגתי ל-ASP.NET Framework, אם ל-shared library יש תלות ישירה ב-HttpContext.Current או ב-System.Web, זה די קשה.

האסטרטגיה הבסיסית כאן היא אחת מאלה:

  • דחיפת התלות ב-System.Web אל מחוץ לממשק
  • שינוי לקבלת מידע שמקורו ב-HttpContext כ-DTO
  • שימוש ב-adapter בתקופת המעבר
  • אם עדיין קשה, הסרה הדרגתית עם multi-target

8.6 מעלים ספריות בשיטת leaf-first

במדריך ה-incremental migration של ASP.NET כתוב במפורש שמעלים supporting library ב-postorder depth-first, כלומר מהעלים ראשון.

זה לא מוגבל ל-Web, אלא יעיל מאוד גם בפתרונות רגילים.

  • מכיוון שהיעדים שהם תלות עלו קודם, קל יותר לראות את השכבה העליונה
  • קל יותר לבודד בעיות תאימות
  • קל יותר לבדוק ברמת ספרייה
מעלים בשיטת leaf-firstתרשים המראה שאם מעלים את ספריות התמיכה מהעלים של התלות ראשון, שכבת הביניים אחריהן, ולבסוף שכבת היישום העליונה, קל יותר לבודד בעיות ולבדוק ברמת ספרייה.מעלים ראשית את ספריות העליםמעלים את שכבת הביניים שסיימהלבסוף שכבת היישום העליונהאפשר לבודד ולבדוק בעיות

איור 26: כשמעלים מהעלים ראשון, עד שמגיעים לשכבה העליונה, הבסיס כבר מוכן.

9. סורקים NuGet / תלויות חיצוניות / רכיבי צד שלישי

אם עושים את זה ברשלנות, זה יכאב הכי הרבה בשלב השני של המעבר.

9.1 נוח יותר לחלק את התלויות לארבעה סוגים

  1. חבילת NuGet ציבורית
  2. חבילה פרטית פנימית / ספרייה internal
  3. הפניית DLL מקומית
  4. COM / ActiveX / DLL native /‏ SDK

מתוכם, לא מספיק להסתכל רק על 1. מה שבאמת מסוכן הם 3 ו-4.

ארבע קטגוריות התלות ורמת הסיכוןתרשים המראה שהתלויות מחולקות לחבילת NuGet ציבורית, חבילה פנימית, הפניית DLL מקומית, ו-COM/ActiveX/DLL native, ושהמסוכנים באמת הם ההפניה המקומית וה-COM/native.ממפים תלויותNuGet ציבורית / חבילה פנימיתהפניית DLL מקומיתCOM / ActiveX / DLL nativeהמסוכן באמת הוא הצד הזה

איור 27: לא מספיק לספור NuGet ציבורי — קודם סורקים DLL מקומי ו-COM / native.

9.2 מה בודקים בכל תלות

לגבי כל תלות, לפחות בודקים עד כאן:

  • האם היא ממוקדת ל-‎.NET מודרני
  • האם היא תומכת ב-PackageReference
  • האם אין בעיה עם סגנון SDK
  • האם יש מגבלה ל-x86 /‏ x64 /‏ ARM64
  • האם היא תלויה בכלי זמן עיצוב או בתוסף Visual Studio
  • האם היא מניחה install script / config transform
  • האם התמיכה עדיין נמשכת

9.3 UI / דוחות / רכיבי צד שלישי לזמן עיצוב — מאמדים בנפרד

במעבר WinForms /‏ WPF /‏ ASP.NET, זה משפיע משמעותית.

  • Grid
  • מנוע דוחות
  • רכיב פלט PDF
  • רכיב גרפים
  • ספריית UI משולבת עם designer
  • עטיפת ActiveX

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

9.4 בודקים תמיד DLL native ו-bitness

גם אם נראה שרץ ב-AnyCPU בתקופת ‎.NET Framework, ייתכן שבפועל יש תלות בדברים מהסוג הבא:

  • COM שקבוע ל-x86
  • ActiveX ייעודי ל-32bit
  • גרסה מסוימת של VC++ Runtime
  • ‏DLL native חתום

זו לא בעיה חדשה שצמחה עם ההפיכה ל-‎.NET מודרני, אלא מגבלה שהייתה קיימת מהתחלה, וצפה עכשיו. בדיוק בגלל זה שווה לחשוף אותה לפני המעבר.

הצפת מגבלת ה-bitnessתרשים המראה שגם אם נראה שרץ ב-AnyCPU, ייתכן תלות ב-COM קבוע ל-x86, ActiveX ל-32bit או גרסה מסוימת של VC++ Runtime, ושאלה מגבלות שהיו קיימות מהתחלה שצפות בגלל המעבר.נראה שרץ ב-AnyCPUתלות ב-COM x86, ActiveX 32bit וכדומההמעבר גורם למגבלה הקיימת לצוףחושפים אותה לפני המעבר

איור 28: בעיית ה-bitness לא נוצרת על ידי המעבר, אלא מגבלה קיימת שנעשית גלויה.

10. מטפלים ב-EF6, בסריאלייזרים ובנתונים כבעיה נפרדת

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

10.1 המעבר מ-EF6 ל-EF Core הוא לא שדרוג ישיר

גם במדריך ה-EF של Microsoft כתוב ש-EF Core הוא כתיבה מחדש מלאה של EF6, ואין נתיב שדרוג ישיר.

לכן, ביישום שמשתמש ב-EF6, הסדר הבא ריאלי:

  1. קודם עוברים ל-‎.NET מודרני
  2. אם צריך, ממשיכים להריץ עם EF6 כמו שהוא
  3. אחר כך מעבירים ל-EF Core כפרויקט נפרד

לא לערבב בין runtime migration ל-ORM migration. רק זה כבר מוריד משמעותית את הקושי.

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

איור 29: לא מריצים בו-זמנית runtime ו-ORM — מעשי יותר להשאיר את EF6 קודם ולהעביר את זמן הריצה.

10.2 מה משתנה כשמשאירים EF6

  • יתרון
    • אפשר לדחות את ההפרש בשכבת גישת הנתונים
    • אפשר להתמקד בהעברת לוגיקת העסק ומודל היישום
    • “הבדל התנהגות של EF Core” לא מתערבב
  • הערה
    • מנקודת מבט של פיתוח חדש, EF Core הוא הבחירה העיקרית
    • יש מגבלות נפרדות לצורת שימוש עם EF6 Designer /‏ EDMX

10.3 EF6 מבוסס EDMX דורש התייחסות גם “בזמן עיצוב”

בתיעוד EF6 כתוב ש-EF Designer לא נתמך ישירות בפרויקטי ‎.NET /‏ ‎.NET Standard, או בפרויקטי ‎.NET Framework בסגנון SDK.

ביישום מבוסס EDMX, צריך להתייחס בנפרד לשלוש נקודות אלה:

  • האם זה פועל בזמן ריצה
  • האם ה-Designer שמיש
  • איך מטפלים בקוד שנוצר

אם יש שימוש נרחב ב-EDMX, בטוח יותר לכלול את זה באומדן כבר מההתחלה.

10.4 BinaryFormatter וסריאליזציה עצמית נוטים להיות “תלות נסתרת”

קל לפספס סריאלייזרים רק בעזרת חיפוש קוד.

  • פורמט נתונים לשמירה
  • מסרים
  • מטמון
  • חוזה WCF / SOAP ישן
  • ResX
  • clipboard / drag & drop

אלה קשורים גם לתאימות נתונים. כלומר, לא מספיק “האם ה-build עובר”, אלא נדרשת בדיקה עד להאם אפשר לקרוא נתונים ישנים.

11. כוללים גם תצורה, הפצה, תפעול ו-CI/CD ביעד המעבר

יעד המעבר הוא לא רק קוד המקור.

11.1 קובצי תצורה

בצד ‎.NET Framework, לעיתים יש הרבה מוטמע ב-app.config /‏ web.config.

  • מחרוזת חיבור
  • section תצורה מותאם
  • הגדרת endpoint של WCF
  • ‏binding redirect
  • אבחון
  • הגדרות שונות של ASP.NET
  • תוצאת ה-transform בזמן התקנת חבילה

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

מה שעושים ראשון הוא מיפוי התצורה.

  • מה מוטמע בקובץ התצורה
  • מה חובה בזמן הפעלת היישום
  • מה הפרש שבין סביבות
  • מה הוזרק אוטומטית על ידי NuGet או installer

11.2 שיטת ההפצה

גם צורת ההפצה נבדקת לפני תחילת העבודה.

  • תחת IIS
  • שירות Windows
  • Scheduled Task
  • ClickOnce /‏ MSI / installer עצמאי
  • הנחת שרת מקומי
  • מה מתאים יותר — self-contained או framework-dependent

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

11.3 לוגים, ניטור, נהלי תפעול

גם סביב התפעול קל לפספס.

  • האם מבוסס Windows Event Log
  • האם מסתכלים על Performance Counter
  • האם ניטור מבוסס WMI
  • האם חשבון השירות וההרשאות קבועים
  • האם יעד פלט הלוגים מניח קובץ מקומי

קורה בהחלט שהקוד רץ אחרי המעבר, אבל התפעול לא מסתובב.

11.4 CI/CD ו-build agent

לפני המעבר, בודקים גם את אלה:

  • האם ה-.NET SDK הנדרש נכנס ל-build agent
  • מה עושים עם pipeline שמניח nuget.exe /‏ msbuild.exe
  • האם עוברים בסיס dotnet CLI
  • איך מעדכנים את עבודות הריצת הבדיקות, coverage ו-publish
  • האם תבנית פנים-ארגונית או reusable pipeline מניחים צורה ישנה

עובד בסביבה המקומית של האדם אבל ה-CI מת זו תופעה נפוצה במעבר.

יעד המעבר הוא לא רק הקודתרשים המראה שגם אם גוף ההרצה עובר, אם קובצי התצורה, שיטת ההפצה, הלוגים והניטור, וה-CI/CD ו-build agent נשארים בהנחה ישנה, זה נתקע בסוף, ולכן כל אלה נכללים ביעד המעבר.מעבר קוד המקורזה לא מסתיים בזה בלבדקובצי תצורה ושיטת הפצהלוגים, ניטור, נהלי תפעולCI/CD ו-build agentעובד מקומית אבל ה-CI מת

איור 30: רק כשכוללים תצורה, הפצה, תפעול ו-CI/CD, זה נחשב שסופרו כל יעדי המעבר.

12. אופן ההתקדמות המעשי של המעבר

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

12.1 קודם מסדרים את צד ה-Framework הנוכחי

  1. עלייה ל-‎.NET Framework 4.7.2 ומעלה, אם אפשר ל-4.8.1
  2. עדכון התלויות
  3. בדיקה מחדש של packages.config
  4. ככל האפשר, מעבר ל-PackageReference ולסגנון SDK
  5. אימות שהיישום הנוכחי רץ תקין במצב הזה

רק ביצוע השלב הזה מצמצם משמעותית את ההפרש בשלב הבא.

12.2 מצילים קודם shared library

בשלב הבא, מעבירים לוגיקה עסקית וחוזים משותפים ל-netstandard2.0 או ל-multi-target. סדר ההעלאה הבסיסי הוא leaf-first.

12.3 מחליפים אסטרטגיה לגוף היישום לפי מודל היישום

  • ספריית מחלקות / מסוף / חלק מהשירותים יחסית קל להתקדם ישירות
  • WinForms /‏ WPF מודרניזציה תוך שמירה על ייעודיות ל-Windows
  • ASP.NET MVC /‏ Web API אם קטן — בבת אחת, אם כבד — הדרגתי
  • Web Forms בהנחת החלפת נכסי המסך, מוציאים תחילה לוגיקה משותפת
  • שרת WCF קובעים קודם — שמירת CoreWCF, או תכנון מחדש עם gRPC

12.4 שומרים על “לא לעשות הכול בבת אחת”

בפרט, מה שכדאי להימנע ממנו הוא שילובים מהסוג הבא:

  • מעבר runtime + החלפה כוללת ל-ORM
  • מעבר runtime + שינוי תשתית אימות
  • מעבר runtime + מעבר מלא לענן
  • מעבר runtime + שינוי תשתית ניטור
  • מעבר runtime + חידוש תשתית UI

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

12.5 פועלים רק אחרי שיש בדיקות וקו בסיס

לפחות, כדאי להכין את זה לפני שמתחילים לפעול:

  • בדיקות יחידה
  • בדיקות אינטגרציה לזרימות עסק מרכזיות
  • אימות “תמונת מצב” למסכים / API-ים ייצוגיים
  • קו בסיס ביצועים
  • שיטת אימות לוגים מרכזיים
  • נוהל rollback

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

מה מכינים לפני שמתחילים לפעולתרשים המראה שאם מכינים בדיקות וקו בסיס, לוגים ונהלי rollback לפני שמתחילים לפעול במעבר, אפשר לזהות מה נשבר אחריו, ואילו התקדמות בלי הכנה מסוכנת.הכנת בדיקות וקו בסיסרק אז מתחילים לפעול במעבראפשר לזהות מה נשברהתקדמות בלי הכנהאי-זיהוי במקרה תקלה — מסוכן

איור 31: המעבר נקבע לפי ההכנה שלפני הפעולה, ורק עם קו בסיס אפשר לזהות מה נשבר.

13. רשימת בדיקה לפני תחילת העבודה

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

13.1 מדיניות

  • אפשר להסביר במשפט אחד למה עושים את המעבר
  • נקבע האם נקודת ההגעה הפעם היא ‎.NET מודרני ייעודי ל-Windows, או חוצה-פלטפורמות בעתיד
  • נקבעה גרסת ‎.NET היעד
  • נקבע מה לא נכלל בהיקף הזה (הפיכה ל-EF Core, חידוש אימות, מעבר מלא לענן וכדומה)

13.2 סידור צד ‎.NET Framework הנוכחי

  • הועלה ל-‎.NET Framework 4.7.2 ומעלה, אם אפשר ל-4.8.1
  • התלויות עלו לגרסה עדכנית
  • נסרק קיום packages.config
  • נבדקה היתכנות הפיכה ל-PackageReference
  • נבדקה היתכנות מעבר לסגנון SDK
  • היישום הנוכחי מסוגל ל-build, הפעלה ובדיקה במצב הזה

13.3 סוג היישום ובחירת טכנולוגיה

  • הקושי חולק לפי סוג — ספריית מחלקות / שולחני / Web / WCF וכדומה
  • מובן ש-WinForms /‏ WPF נשארים ייעודיים ל-Windows
  • מובן ש-ASP.NET Framework הוא מעבר מודל יישום ל-ASP.NET Core
  • הוכללה באומדן החלפת שכבת UI ל-Web Forms
  • WCF הוערך בנפרד ללקוח ולשרת

13.4 טכנולוגיות לא נתמכות / API-ים שדורשים תשומת לב

  • נסרקה תלות ב-AppDomain
  • נסרקו Remoting /‏ MarshalByRefObject /‏ BeginInvoke /‏ EndInvoke
  • נסרקו CAS / Security Transparency /‏ COM+ /‏ WF
  • נסרקה תלות ב-BinaryFormatter
  • נסרקה תלות ב-System.Web

13.5 תלות ייעודית ל-Windows

  • נסרק שימוש ברישום המערכת,‏ WMI,‏ EventLog, שירות Windows,‏ Directory Services
  • נסרק שימוש ב-System.Drawing.Common
  • נסרקו COM / ActiveX / Office Interop / P/Invoke / DLL native
  • נבדקה מגבלת x86 /‏ x64 /‏ ARM64

13.6 shared library וגישה לנתונים

  • shared library סווגו ללוגיקה עסקית / שכבה צמודה למודל יישום
  • נסרק מה ניתן להפוך ל-netstandard2.0
  • נסרקו ספריות שדורשות multi-target
  • נקבע האם אפשר להשאיר EF6 ולהעביר קודם רק את זמן הריצה
  • נבדקה תלות EDMX / Designer

13.7 תפעול ו-build

  • בוצע מיפוי קובצי תצורה
  • נבדקה שיטת ההפצה (‏IIS / Service / MSI /‏ ClickOnce וכדומה)
  • נבדקו הנחות לוגים / ניטור / הרשאות / חשבון הרצה
  • נבדק האם נדרש עדכון ל-CI/CD ול-build agent
  • הוכן נוהל rollback

14. סיכום

במעבר מ-‎.NET Framework ל-‎.NET, מה שחשוב הוא לא “באיזו פקודה מעבירים”, אלא לזהות לפני תחילת העבודה מה עובר כמו שהוא ומה בעיה נפרדת.

אם מרכזים לנקודות, הנה שש אלה:

  • מסדרים את צד ‎.NET Framework לפני המעבר
  • מחלקים את הקושי לפי מודל היישום
  • סורקים קודם טכנולוגיות שלא ניתן להשתמש בהן
  • קובעים עד כמה מקבלים הנחת יסוד ייעודית ל-Windows
  • קובעים איך חותכים את ה-shared library
  • לא לוקחים יותר מדי בבת אחת מ-ORM, אימות ומעבר לענן

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

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

איור 32: האם השבוע הראשון מנוצל למיפוי, קובע את דיוק המעבר כולו.

“בואו פשוט ננסה לשנות ל-net10.0” הוא לא רעיון רע לצורך חקירה. עם זאת, כמעבר בפועל לייצור, יש מה לבדוק לפני זה. זה בדיוק מה שסידרנו במאמר הזה.

15. מקורות

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

העמודים האלה ממקמים את הנושא בהקשר רחב יותר של שירותים והחלטות.

המאמר קשור ישירות לשירותים הבאים.

שאלות נפוצות

שאלות נפוצות בפניות בנושא המאמר.

מה כדאי לעשות קודם לפני מעבר מ-‎.NET Framework ל-‎.NET?
לפני שנכנסים למימוש, קודם מסיימים את הסידור בצד ‎.NET Framework. גם המדריך הרשמי של Microsoft ממליץ, לפני ההעברה, לעלות ל-‎.NET Framework 4.7.2 ומעלה (בעבודה מעשית, אם אפשר, 4.8.1), להפוך את packages.config ל-PackageReference, לעבור לסגנון פרויקט SDK, ולעדכן תלויות לגרסה עדכנית יותר. אם עושים את זה קודם, ההפרש בשלב הבא של המעבר ל-‎.NET מודרני מצטמצם משמעותית, וקל יותר להבחין אם מקור בעיית תאימות הוא 'ה-Framework הישן' או 'המעבר ל-‎.NET'. במקביל, גם מבצעים מיפוי של טכנולוגיות לא נתמכות כמו AppDomain,‏ Remoting ו-BinaryFormatter לפני תחילת העבודה.
האם אפשר להחליט להישאר עם ‎.NET Framework?
כן, זו החלטה סבירה לגמרי. ‎.NET Framework 4.8.1 ממשיך לקבל תמיכה כל עוד הוא מותקן על Windows נתמך, ולכן זה לא מצב שבו חייבים מיד להעביר הכול ל-‎.NET מודרני. אם יש נכסי מסך רבים ב-Web Forms, צריך לשמור בקפדנות על תאימות שרת WCF, יש תלות עמוקה ב-Workflow Foundation או ב-COM+, או שרכיבי צד שלישי לזמן עיצוב לא נתמכים — הגיוני להישאר בינתיים על 4.8.1 עם תפעול יציב, ולתכנן החלפה בקו נפרד. עם זאת, נשארות מגבלות כמו אי-יכולת לצאת מ-Windows בלבד, וקושי ליהנות מביצועים ותכונות שפה חדשות של ‎.NET.
אילו טכנולוגיות לא ניתן להעביר ל-‎.NET, או שקל להיתקע בהן?
יצירת AppDomain,‏ ‎.NET Remoting,‏ CAS (אבטחת גישה לקוד),‏ COM+‏ (System.EnterpriseServices) ו-Workflow Foundation לא נתמכים ב-‎.NET מודרני, ואלה תמרורי אזהרה שדורשים תכנון מחדש. שרת WCF לא רץ כמו שהוא built-in, ויש לבחור בין תכנון מחדש עם CoreWCF ל-gRPC /‏ HTTP API. BinaryFormatter, מ-‎.NET 9 ואילך, לא כולל מימוש וזורק תמיד חריגה, ולכן נדרש ביקורת שכוללת נתונים שנשמרו, ResX וגם clipboard / drag & drop. בנוסף, המרות install.ps1 /‏ XDT של packages.config,‏ DLL‏ native,‏ COM / ActiveX, והנחת x86 — כל אלה נקודות שדורשות תשומת לב, כי גם אם ה-build עובר, קל ליפול בזמן ריצה.
האם מעבר יישום WinForms או WPF ל-‎.NET הופך אותו לחוצה-פלטפורמות?
לא. WinForms /‏ WPF יכולים לעבור ל-‎.NET, אבל הם נשארים תשתיות ייעודיות ל-Windows. מה שמתקבל מהמעבר הוא ההטבות של זמן ריצה, תכונות שפה, סגנון SDK ותאימות ל-CI/CD של ‎.NET מודרני, אבל זה לא הופך אותם לתומכים במכולות Linux. אם שואפים בעתיד ל-Linux / הכלה במכולה, צריך לבצע מיפוי מוקדם ל-API-ים שמניחים Windows כמו System.Drawing.Common, רישום המערכת,‏ WMI,‏ EventLog, שירות Windows ו-Office Interop. לעומת זאת, אם ממשיכים להישאר ייעודיים ל-Windows, אפשר לבחור במסלול מעשי שמפעיל תחילה מודרניזציה של זמן הריצה בעזרת Windows Compatibility Pack.

פרופיל הכותב

עמוד היכרות עם כותב המאמר.

Go Komura

מנהל KomuraSoft LLC

מתמחה בפיתוח תוכנה עבור Windows, ייעוץ טכני וחקירת תקלות, בעיקר בפרויקטים עם מערכות קיימות ובאגים שקשה לשחזר.

קישורים ציבוריים

חזרה לבלוג