EF WPF Selective SaveChanges
-
באנטיטי,
נאמר שאני יוצר איש קשר
כאשר אני יוצר אותו לראשונה הפעולה המתבקשת היא
להוסיף אותו לאנטיטי ע"י:
Contacts.Add(Contact); ולאחר מכן:
db.SaveChanges();
כאשר רק ביצעתי שינוי כגון הוספת מספר טלפון לאיש שקיים במערכת אבצע רק:
db.SaveChanges(); שבעצם פעולה זו שומרת את כל השינויים במערכת כגון הרכישות של האיש קשר
ומכאן לבעיה:
באפליקציה ישנם הרבה חלונות שביקרתי בהם (כגון בחלון הרכישות) ובצעתי שם שינויים אך בסופו של דבר התחרטתי ולכן לא לחצתי על שמירה, בכל זאת כעת כאשר אבצע SaveChanges האנטיטי יכיל לי א"ז על כל הפריטים של האנטיטי
מה שאני חושב שזה כנראה קשור לזה שאני משתמש בהרבה מקומות בתוכנה אם נוטיפיי אבל זה הצורך
אז מה הפיתרון בכזה מצב שאוכל לשלוט על השינויים של ה-SaveChanges ?תודה רבה!
פורסם במקור בפורום CODE613 ב11/09/2014 01:06 (+03:00)
-
זה לא תמיד יהיה נכון לעשות מופע חדש
לדוגמא כאשר מוסיפים איש קשר ומיד אח"כ בחלון אחר (דטה קונטקסט חדש) רוצים לעשות שינוי לאיש קשר במקרה כזה הוא יתווסף מחדש לדטה בייס מאחר ובדטה קונטקסט הנוכחי הוא לא מכיר את האיש קשר הזהפורסם במקור בפורום CODE613 ב11/09/2014 09:58 (+03:00)
-
השאלה נחלקת לשניים:
א. איך אפשר לשמור נתון בודד, ולהשאיר את האחרים במצב דורש שמירה (כי בנקודת זמן זו המשתמש נגיד עדיין יכול ללחוץ על ה"ביטול").
ב. איך לבטל שינויים אותם לא מעוניינים כלל לשמור. נאמר הוספנו אייטם או שינינו ולבסוף החלטנו לא לשמור = לבטל, כדי שמכאן ולהבא השינויים לא יעמדו על הפרק כלל.לשאלה הראשונה:
הסיטואציה הזו נדירה, ויש לבדוק היטב אם המצב הזה נצרך (ראה נ.ב. בסוף). במקרה וכן, מה שצריך זה ליצור DbContext ספציפית לנתון הדרוש. זה לא סותר במאומה את הDbContext הראשי שמשותף לכל החלונות, ויכול לרוץ במקביל אליו. כמו"כ לא צריך לתשאל מחדש את המסד אם מדובר בעדכון שדה, כי אפשר להשתמש עם הID ולשנות ידנית את הSTATE לMODIFIED.לשאלה השניה:
בעיקרון אפשר לשחזר את הDbContext לקדמותו בכמה דרכים, אבל הכי פשוט זה לא להזדקק לזה. למשל, במקרה תיבת דו שיח של הוספת איש קשר, שכשבלחיצה על האישור נעשה SaveChanges, אז במקרה ביטול אין להסתפק בהיעדרה של הפקודה SaveChanges, אלא להסיר את האיש קשר מהDbContext כדי שההוספה כבר לא תעמוד על הפרק:DbContext.Table.Remove(Item);
במקרה של עריכה, אפשר פשוט לקבוע את הערך של EntityState כUnchanged, וממילא הDbContext לא ישלח עדכון על אייטם זה. בשביל לשחזר את הערכים המקוריים לאייטם שבזיכרון הDbContext אפשר ככה:
var entry = DbC.Entry(Item); entry.CurrentValues.SetValues(entry.OriginalValues); entry.State = EntityState.Unchanged;
או (מיותר קצת) לתשאל את הDB שוב לגבי פריט זה ע"י פקודת Refresh של הDbContext.
נ.ב.
על השאלה הראשונה יש להעיר, כי בכלל לא חייבים "להיכנס לזה", כלומר הכי פשוט זה לא לשמור כלל בנקודת זמן זו. למשל אם יש אפשרות ליצור איש קשר חדש, ובעוד התיבת הדו שיח ממתינה לאישור/ביטול אז יש אפשרות לצרף ל"איש" המיועד טלפונים, ונאמר שהטלפונים זה טבלה נפרדת. אז אכן לא כדאי לעשות SaveChange להוספת טל', כל עוד לא בטוח כלל שילחץ ה"אישור" להוספת ה"איש קשר".פורסם במקור בפורום CODE613 ב11/09/2014 11:05 (+03:00)
-
זה לא תמיד יהיה נכון לעשות מופע חדש
עניין של גישה, אכן אני בעד זו שלך.
שים לב שבווב זו לא אופציה...לדוגמא כאשר מוסיפים איש קשר ומיד אח"כ בחלון אחר (דטה קונטקסט חדש) רוצים לעשות שינוי לאיש קשר במקרה כזה הוא יתווסף מחדש לדטה בייס מאחר ובדטה קונטקסט הנוכחי הוא לא מכיר את האיש קשר הזה
זה כבר לא טענה, כי זה רק עניין של קצת קוד נוסף: צריך לקבוע ידנית את הState לModifeid ולהוסיף לDbContext החדש ולשמור וזהו.
פורסם במקור בפורום CODE613 ב11/09/2014 11:22 (+03:00)
-
@דוד ל.ט.
במקרה של עריכה, אפשר פשוט לקבוע את הערך של EntityState כUnchanged, וממילא הDbContext לא ישלח עדכון על אייטם זה. בשביל לשחזר את הערכים המקוריים לאייטם שבזיכרון הDbContext אפשר ככה:
var entry = DbC.Entry(Item); entry.CurrentValues.SetValues(entry.OriginalValues); entry.State = EntityState.Unchanged;
לסיכומו של דבר כך עשיתי: דטה קונטקסט אחד להכל וכשיוצאים מחלון בלי לעשות שמירה מתבצע אוטומטי ביטול ע"י הקוד הנ"ל,
מבחינתי זה הגישה שפתרה לי את הבעיה לשביעות רצוני
בכל אופן תודה רבה לכולםפורסם במקור בפורום CODE613 ב14/09/2014 22:27 (+03:00)