serilization לכל התוכנה
-
בכל תוכנה כמעט יש את התיקיה הראשית של התוכנה ותיקיית 'יוזר-דטה'
בברירת מחדל שים את תקיית 'הגדרות משתמש' בתיקיית מערכת ידועה הנקראת 'מסמכים שלי', וזה הכי טוב ואל תסבך אותו עם בחירת מקום
אם אתה דווקא רוצה לתת לו לבחור, תן לו לבחור תיקיה שבה ישמרו כל הגדרות המשתמש שלו
בכל אופן תיצור תיקייה של יוזר-דטה כנל ובתוכה עוד תיקיה של 'נתונים'
באופן כללי זה לא טוב לשמור נתונים רק בסגירה, כיון שהתוכנה יכולה לקרוס באמצע [אם בגלל חשמל, התעוררות משינה בצורה לא תקינה, באג בתוכנה ועוד] והמשתשמ יאבד נתונים אלא יש לשמור כל פרק זמן או אחר כל שינוי.פורסם במקור בפורום CODE613 ב30/07/2015 12:45 (+03:00)
-
אני ממש בור בנושא הזה, ולכן יש לי כמה שאלות פשוטות, אבל אני מסתבך בזה כבר הרבה זמן..
@רחמיםבכל תוכנה כמעט יש את התיקיה הראשית של התוכנה ותיקיית 'יוזר-דטה'
בברירת מחדל שים את תקיית 'הגדרות משתמש' בתיקיית מערכת ידועה הנקראת 'מסמכים שלי', וזה הכי טוב ואל תסבך אותו עם בחירת מקוםאם אני מבין נכון, התיקייה הראשית הכוונה לתיקייה שבה נשמרים קבצי ההרצה של התכנית וכדו' והיא נוצרת בזמן ההתקנה במיקום שהוא בוחר להתקין את התכנית. ותיקיית 'יוזר דטה' היא התיקייה עם הנתונים שהוא מזין לתוכנה, ואתה ממליץ להגדיר שהיא תשב בתוך 'המסמכים שלי'.
@רחמיםאם אתה דווקא רוצה לתת לו לבחור, תן לו לבחור תיקיה שבה ישמרו כל הגדרות המשתמש שלו
איך אני נותן לו לבחור רק תיקייה ולא לבחור קובץ? אני מכיר את הדיאלוג של שמירת הקבצים שבו הוא יכול לבחור איפה לשמור את הקובץ ובאיזה שם לקרוא לו, אך אינני מכיר דיאלוג של בחירת ספרייה לבד. או שאתה מתכוון שאני אצור כזה דבר לבד?
@רחמיםבכל אופן תיצור תיקייה של יוזר-דטה כנל ובתוכה עוד תיקיה של 'נתונים'
למה ליצור שתי תיקיות של נתונים?
תודה רבה רבה!פורסם במקור בפורום CODE613 ב30/07/2015 12:55 (+03:00)
-
אם אני מבין נכון, התיקייה הראשית הכוונה לתיקייה שבה נשמרים קבצי ההרצה של התכנית וכדו' והיא נוצרת בזמן ההתקנה במיקום שהוא בוחר להתקין את התכנית. ותיקיית 'יוזר דטה' היא התיקייה עם הנתונים שהוא מזין לתוכנה, ואתה ממליץ להגדיר שהיא תשב בתוך 'המסמכים שלי'.
נכון
איך אני נותן לו לבחור רק תיקייה ולא לבחור קובץ? אני מכיר את הדיאלוג של שמירת הקבצים שבו הוא יכול לבחור איפה לשמור את הקובץ ובאיזה שם לקרוא לו, אך אינני מכיר דיאלוג של בחירת ספרייה לבד. או שאתה מתכוון שאני אצור כזה דבר לבד?
יש את זה Windows.Forms.FolderBrowserDialog זה לא נכלל בברירת מחדל ב WPF אלא בוינפורמס
אתה גם יכול ליצור לבד, למה לא אני בעד.למה ליצור שתי תיקיות של נתונים?
בתיקיית של יוזר-דטה אתה תשמור נתונים שונים לא רק הקשורים לליסטים שהם יחידה בפני עצמה אלא גם העדפות ממשק שונות וכדומה ולכן יש לעבוד בצורה מסודרת לשים כל דבר בתיקיה בפני עצמה.
פורסם במקור בפורום CODE613 ב30/07/2015 13:06 (+03:00)
-
כמה פשוטים חייהם של מי שכותב עם DB.
אני מניח שאתה רק רוצה ללמוד איך עובדים עם קבצים + serilization.
כי אם לא, אני עדיין חושב שיהיה לך יותר קל לחזור / לעבור לDBודאי וודאי!
אני רוצה לחזור לדטה בייס, ואני רוצה להתחיל ללמוד איך לעבוד עם הEF בצורה של codeFirst
כי עם הדטהסט קצת הסתבכתי..
לבינתיים אני מנסה לגמור את הפרוייקט שכבר התחלתי, כדי שלא אתפזר יותר מדי... :lol:פורסם במקור בפורום CODE613 ב30/07/2015 13:22 (+03:00)
-
זה שהסתבכת עם דטהסיט לא סיבה לעבור לEF הוא לא פחות מסובך, וגם שהוא כלל לא יציב כל תקופה קצרה יוצאת לו גירסה חדשה ושוב אתה צריך ללמוד מה חדש, וזה רק מלמד שמיקרוסופט עדיין לא החליטו סופית לגביו ולכן כל רגע מוציאים לו גירסה חדשה.
אנשים עוברים לEF בגלל שהוא מספק את הצרכים שלהם בצורה טובה יותר.פורסם במקור בפורום CODE613 ב30/07/2015 13:26 (+03:00)
-
זה שהסתבכת עם דטהסיט לא סיבה לעבור לEF הוא לא פחות מסובך, וגם שהוא כלל לא יציב כל תקופה קצרה יוצאת לו גירסה חדשה ושוב אתה צריך ללמוד מה חדש, וזה רק מלמד שמיקרוסופט עדיין לא החליטו סופית לגביו ולכן כל רגע מוציאים לו גירסה חדשה.
אנשים עוברים לEF בגלל שהוא מספק את הצרכים שלהם בצורה טובה יותר.אני מבין את התחושה אבל חולק. הEntityFramwork כבר תפס מקום שאין ממנו חזרה. והגרסאות שיוצאות חדשות לבקרים הם השבחות שלא מחייבים אותך ללמוד לגביהם, והם לא סותרים את הקיים (למעט גירסאות הבטה). גם יש תמיכה רשמית לגירסאות ישנות וזה מראה ששמים על זה את כובד המשקל.
קח למשל את LinqToSql שלא יוצאים לו גירסאות כי מבחינת מקרוסופט הוא טעות... ההבדל הוא שאת LinqToSql עשו מפתחי הLinq כגימיק להראות את עוצמתה של הLinq והם ייעדו את זה נטו לSQL SERVER וגם זה בצורה חפיפית. ואילו EF נוצר ע"י מפתחי הADO.NET, ששמו את כל כובד משקלם שזה יהיה הדרך בה"א הידיעה לגישה לנתונים.פורסם במקור בפורום CODE613 ב30/07/2015 13:32 (+03:00)
-
יש את זה Windows.Forms.FolderBrowserDialog זה לא נכלל בברירת מחדל ב WPF אלא בוינפורמס
אתה גם יכול ליצור לבד, למה לא אני בעד.יש אפשרות לעשות לזה רפרנס מWPF? כי לא הצלחתי..
ולגבי הEntity נשמע לי יותר הגיוני לעבוד מול המחלקות שלי, ורק בסוף לשמור הכל לדטהבייס..
אבל באמת שאני לא מבין בזה..פורסם במקור בפורום CODE613 ב30/07/2015 14:22 (+03:00)
-
מה שעשיתי בסופו של דבר:
כתבתי מחלקה של סריליזציה ודסריליזציה,
אני נותן למשתמש לבחור את התיקייה הרצויה עליו (או ליצור חדשה) ובה נשמרים הנתונים.
בתיקייה שהוא בחר אני יוצר (מאחורי הקלעים) עוד 2 תיקיות משנה: userdata ו data כמו שרחמים המליץ.
בתוך התיקייה דטה אני שומר כל ליסט בתור קובץ נפרד.
בפתיחה של הקבצים, הוא בוחר את התיקייה הראשית שהוא יצר, ואני לבד פותח את הקבצים מתוך תיקיות המשנה.כתבתי את הקוד הבא: (אזהרה - קצת ארוך :lol: )
public static class SerilizationAll { //סריליזציה של כל התכנית public static void Serilization() { FolderBrowserDialog folderBrowser = new FolderBrowserDialog(); if (folderBrowser.ShowDialog() == DialogResult.OK) { string folder = folderBrowser.SelectedPath; folder += @"\userData\data";//מוסיף לנתיב תיקיית משנה לשמירת הנתונים DirectoryInfo directoryInfo = new DirectoryInfo(folder); directoryInfo.Create();//יוצר את ספריות המשנה serilizationList(folder);//קורא למתודה שמבצעת את הסריליזציה } } //סריליזציה של כל הליסטים מקבלת את הערך של התיקייה לשמירת הנתונים public static void serilizationList(string folder) { //יוצר את שמות הקבצים עבור כל הליסטים string fileDonor = folder; string fileDonation = folder; string fileCredit = folder; string fileBank = folder; fileDonor += @"\donorList"; fileDonation += @"\donationList"; fileCredit += @"\creditCardList"; fileBank += @"\bankAccountList"; //יוצר אובייקטים המקבלים את רשימות הליסטים הקיימים בתוכנית var donationObject = AddTorem.donations; var donorsObject = AddTorem.donors; var creditObject = AddTorem.credits; var bankObjects = AddTorem.accounts; //סריאליזציה עבור כל ליסט לקובץ נפרד using (FileStream fs = new FileStream(fileDonor, FileMode.Create)) { XmlSerializer donorXmlS = new XmlSerializer(typeof(List<Donor>)); donorXmlS.Serialize(fs, donorsObject); } using (FileStream donatStr = new FileStream(fileDonation, FileMode.Create)) { XmlSerializer donationXmlS = new XmlSerializer(typeof(List<Donation>)); donationXmlS.Serialize(donatStr, donationObject); } using (FileStream creditStream = new FileStream(fileCredit, FileMode.Create)) { XmlSerializer creditXmlS = new XmlSerializer(typeof(List<CreditCard>)); creditXmlS.Serialize(creditStream, creditObject); } using (FileStream bankStream = new FileStream(fileBank, FileMode.Create)) { XmlSerializer bankXMLs = new XmlSerializer(typeof(List<BankAccount>)); bankXMLs.Serialize(bankStream, bankObjects); } } //deserilization for all program public static void Deserilization() { FolderBrowserDialog folderBrowser = new FolderBrowserDialog(); if (folderBrowser.ShowDialog() == DialogResult.OK) { string folders = folderBrowser.SelectedPath; folders += @"\userData\data";//מוסיף לנתיב את הנתיב לתיקיית משנה בה קיימים הנתונים //קורא למתודות שמבצעות את הסריליזציה על התיקייה שנבחרה ומציב את הערך שמתקבל בליסטים הקיימים בתכנית AddTorem.donors= DeserilizationDonor(folders); AddTorem.donations = DeserilizationDonation(folders); AddTorem.credits = DeserilizationCreditCard(folders); AddTorem.accounts = DeserilizationBankAccount(folders); } } private static List<BankAccount> DeserilizationBankAccount(string folders) { string fileBank = folders; fileBank += @"\bankAccountList";//בוחר בקובץ הדרוש var myObject = new List<BankAccount>(); using (FileStream fs = new FileStream(fileBank, FileMode.Open)) { XmlSerializer xmlser = new XmlSerializer(typeof(List<BankAccount>)); myObject = (List<BankAccount>)xmlser.Deserialize(fs); return myObject; } } private static List<CreditCard> DeserilizationCreditCard(string folders) { string fileCredit = folders; fileCredit += @"\creditCardList"; var myObject = new List<CreditCard>(); using (FileStream fs = new FileStream(fileCredit, FileMode.Open)) { XmlSerializer xmlser = new XmlSerializer(typeof(List<CreditCard>)); myObject = (List<CreditCard>)xmlser.Deserialize(fs); return myObject; } } private static List<Donation> DeserilizationDonation(string folders) { string fileDonation = folders; fileDonation += @"\donationList"; var myObject = new List<Donation>(); using (FileStream fs = new FileStream(fileDonation, FileMode.Open)) { XmlSerializer xmlser = new XmlSerializer(typeof(List<Donation>)); myObject = (List<Donation>)xmlser.Deserialize(fs); return myObject; } } private static List<Donor> DeserilizationDonor(string folders) { string fileDonor = folders; fileDonor += @"\donorList"; var myObject = new List<Donor>(); using (FileStream fs = new FileStream(fileDonor, FileMode.Open)) { XmlSerializer xmlser = new XmlSerializer(typeof(List<Donor>)); myObject = (List<Donor>)xmlser.Deserialize(fs); return myObject; } } }
הכל עובד חלק!!! תודה רבה על העזרה והתמיכה!!
השאלה שלי היא האם אי אפשר לייעל את זה, כיון שבסוף נאלצתי לכתוב מתודה נפרדת לפתיחת כל ליסט. האם אי אפשר לכתוב מתודה גנרית שתדע לזהות לבד את הערך של כל ליסט הנשלח אליה ולחלץ אותו?
בטח זה אפשרי, אבל לא הצלחתי.. ניסיתי לכתוב במתודה List<T> אבל זה לא הצליח לי.. אז נאלצתי לכתוב 4 מתודות שבעצם עושות אותו דבר..פורסם במקור בפורום CODE613 ב30/07/2015 15:50 (+03:00)
-
א. מחיאות כפיים.
ב. בכל דסראילציה כתבת var myObject = new ...
מיותר בדסריאלזציה כיון שהדסיאליזר יוצר בעצמו אבייקט (אתה זוכר את זה http://tchumim.com/post/4509).
ג. אכן בדיוק כמו שניחשת ע"י מתודות גנריות אפשר בקלות לעשות פונקציה מרוכזת הן לסריאליזציה ון לדסריאליזציה, תראה קוד:public static class SerilizationAll { const string fileDonor = @"\donorList"; const string fileDonation = @"\donationList"; const string fileCredit = @"\creditCardList"; const string fileBank = @"\bankAccountList"; //סריליזציה של כל התכנית public static void Serilization() { FolderBrowserDialog folderBrowser = new FolderBrowserDialog(); if (folderBrowser.ShowDialog() == DialogResult.OK) { string folder = folderBrowser.SelectedPath; folder += @"\userData\data";//מוסיף לנתיב תיקיית משנה לשמירת הנתונים DirectoryInfo directoryInfo = new DirectoryInfo(folder); directoryInfo.Create();//יוצר את ספריות המשנה Serialize(AddTorem.donations, folder + fileDonation); Serialize(AddTorem.donors, folder + fileDonor); Serialize(AddTorem.credits, folder + fileCredit); Serialize(AddTorem.accounts, folder + fileBank); } } //deserilization for all program public static void Deserilization() { FolderBrowserDialog folderBrowser = new FolderBrowserDialog(); if (folderBrowser.ShowDialog() == DialogResult.OK) { string folders = folderBrowser.SelectedPath; folders += @"\userData\data";//מוסיף לנתיב את הנתיב לתיקיית משנה בה קיימים הנתונים //קורא למתודות שמבצעות את הסריליזציה על התיקייה שנבחרה ומציב את הערך שמתקבל בליסטים הקיימים בתכנית Deserilize(AddTorem.donors, folders + fileDonor); Deserilize(AddTorem.donations, folders + fileDonation); Deserilize(AddTorem.credits, folders + fileCredit); Deserilize(AddTorem.accounts, folders + fileBank); } } private static void Serialize<T>(T obj, string path) { using (FileStream bankStream = new FileStream(path, FileMode.Create)) { XmlSerializer xml = new XmlSerializer(typeof(T)); xml.Serialize(bankStream, obj); } } private static void Deserilize<T>(T returnObj, string path) { using (FileStream fs = new FileStream(path, FileMode.Open)) { XmlSerializer xmlser = new XmlSerializer(typeof(T)); returnObj = (T)xmlser.Deserialize(fs); } } }
בהצלחה רבה!
פורסם במקור בפורום CODE613 ב30/07/2015 16:34 (+03:00)
-
אגב כיון שהתעצלתי ליצור מחלקות כשלך בשביל לקבל תמיכה של השלמה אוטומטית ובדיקת שגיאות, אז בחרתי בדרך של מתודה גנרית לDeserilize, אף שבכל מקרה הוא מחזיר Object וצריך לעשות לו cast, ממילא לך יותר הגיוני לשנות אותו לככה:
private static object Deserilize(string path) { using (FileStream fs = new FileStream(path, FileMode.Open)) { XmlSerializer xmlser = new XmlSerializer(typeof(T)); return xmlser.Deserialize(fs); } }
ובמתודה הקוראת לשנות את זה:
Deserilize(AddTorem.accounts, folders + fileBank);
לזה:
AddTorem.accounts = (Account)Deserilize(folders + fileBank);
עוד הערה, אתה יוצר תיקיה ללא בדיקה מוקדמת - ייתכן שהיא קיימת כבר.
פורסם במקור בפורום CODE613 ב30/07/2015 16:44 (+03:00)
-
בשביל לקצר את הקוד והמורכבות הייתי עושה כך
יוצר מחלקה אבסטרקטית היורשת מליסט או ObservableCollection
מחלקה זו תטפל בכל הנושא של קריאה וכתיבה מהדיסק
וכל הליסטים האחרים של התרומות ותורמים וכו' ירשו ממחלקה אבסטרקטית הנ"ל וכך כל דבר יהיה כתוב רק פעם אחת.
כשתרצה להוסיף ליסט חדש לתוכנה כל שעליך לעשות זה להצהיר שהוא יורש מהמחלקה הנ"ל ולהמציא נתיב שמירה.פורסם במקור בפורום CODE613 ב30/07/2015 17:09 (+03:00)
-
@דוד ל.ט.
תוכל גם במקום להקצות שם לקובץ אחד אחד להשתמש בשם הקלאס ע"י GetType().Name
תיזהר פעם הבאה שאתה מבקש עצות, סכנת הצפה
מעולה!! עצות מחכימות ומועילות!! הלוואי וכל הסכנות היו כאלה :lol:
שיניתי את כל המחלקה כמו שאמרת!!
לגבי העצה לעשות את ההמרה במתודה של הדיסריליזציה לא במתודה עצמה: זה לא עבד לי אלא נתן הודעת שגיאה שאת ההמרה צריך לבצע מיד במקום.בשביל לקצר את הקוד והמורכבות הייתי עושה כך
יוצר מחלקה אבסטרקטית היורשת מליסט או ObservableCollection
מחלקה זו תטפל בכל הנושא של קריאה וכתיבה מהדיסק
וכל הליסטים האחרים של התרומות ותורמים וכו' ירשו ממחלקה אבסטרקטית הנ"ל וכך כל דבר יהיה כתוב רק פעם אחת.
כשתרצה להוסיף ליסט חדש לתוכנה כל שעליך לעשות זה להצהיר שהוא יורש מהמחלקה הנ"ל ולהמציא נתיב שמירה.הבעיה עם זה שאם יש לי מחלקות שיורשות ממחלקות אחרות בתכנית זה לא יועיל, כי אפשר לרשת רק ממחלקה אחת.
תודה רבה רבה על כל העצות!! מה הייתי עושה בלעדיכם :lol:
פורסם במקור בפורום CODE613 ב31/07/2015 08:26 (+03:00)
-
עוד הערה לגבי המתודה של הדיסרילזציה חייבים להציב אותה בערכים המתאימים, ולא מספיק לקרוא לה כמו שכתבת כי הוא כנראה עדיין לא יודע לאן להחזיר את הערך שמתקבל.
ככהAddTorem.donors = Deserilization(AddTorem.donors, folders + fileDonor); AddTorem.donations = Deserilization(AddTorem.donations, folders + fileDonation); AddTorem.accounts = Deserilization(AddTorem.accounts, folders + fileBank); AddTorem.credits = Deserilization(AddTorem.credits, folders + fileCredit);
פורסם במקור בפורום CODE613 ב31/07/2015 09:09 (+03:00)
-
הבעיה עם זה שאם יש לי מחלקות שיורשות ממחלקות אחרות בתכנית זה לא יועיל, כי אפשר לרשת רק ממחלקה אחת.
ספר יותר מה ההיררכיה של המחלקות אצלך בתוכנה, כי בעיקרון כל המחלקות שמחזיקות את הנתונים ומטפלות בנתונים יכולות לרשת אחד מהשני כמה דורות. אולי תביא דיאגרמה.
פורסם במקור בפורום CODE613 ב31/07/2015 11:18 (+03:00)
-
רחמים לא התכוון במחלקות שלך, אלא במקום מחלקת הList תירש הימנה (או מObservablECollection שזה ליסט שנותן נוטיפקציה לשינויים שזה מאוד שימושי בWPF).
@avr416לגבי העצה לעשות את ההמרה במתודה של הדיסריליזציה לא במתודה עצמה: זה לא עבד לי אלא נתן הודעת שגיאה שאת ההמרה צריך לבצע מיד במקום.
אני לא רואה למה.
אם זה לא קשה (זה כן) אז תגיד לי בדיוק איפה השגיאה ומה והאם היא בזמן כתיבה - קומפילציה, או זמן ריצה.פורסם במקור בפורום CODE613 ב31/07/2015 11:39 (+03:00)
-
@דוד ל.ט.
אם זה לא קשה (זה כן) אז תגיד לי בדיוק איפה השגיאה ומה והאם היא בזמן כתיבה - קומפילציה, או זמן ריצה.
דווקא לא קשה כי השגיאה בזמן כתיבה.
הודעת השגיאה היא:
(?Cannot implicitly convert type 'object' to 'T'. An explicit conversion exists (are you missing a castפורסם במקור בפורום CODE613 ב31/07/2015 16:21 (+03:00)