שגיאה מוזרה באנטיטי
-
א. בדוגמא שלהם הם אכן יוצרים מופע חדש של הDB, אם כי הם הורגים קודם כל את השני..
הדוגמא לקוחה מכאןStandard disconnectedStandard = null; using (var context = new SchoolDBEntities()) { context.Configuration.ProxyCreationEnabled = false; disconnectedStandard = context.Standards.Where(s => s.StandardId == 58).Include(s => s.Teachers).FirstOrDefault<Standard>(); } //Update Standard in disconnected mode disconnectedStandard.StandardName = "Edited Standard Name"; //Update teachers collection by editing first teacher and adding new teacher disconnectedStandard.Teachers.ElementAt(0).TeacherName = "Edited Teacher Name"; disconnectedStandard.Teachers.Add(new Teacher() { TeacherName = "New Teacher", StandardId = disconnectedStandard.StandardId }); using (var newContext = new SchoolDBEntities()) { //mark standard based on StandardId newContext.Entry(disconnectedStandard).State = disconnectedStandard.StandardId == 0 ? EntityState.Added : EntityState.Modified; //mark teacher based on StandardId foreach (Teacher tchr in disconnectedStandard.Teachers) newContext.Entry(tchr).State = tchr.TeacherId == 0 ? EntityState.Added : EntityState.Modified; newContext.SaveChanges(); }
כן, זה גוף המתודה:
public static U MapAllObjUIToDAL<T,U>(T objUI,ref U objDAL) { var mapper = reverseConfig.CreateMapper(); mapper.Map<T,U>(objUI,objDAL); return objDAL; }
תודה רבה!
פורסם במקור בפורום CODE613 ב14/11/2017 09:27 (+02:00)
-
ברור שזה יעבוד... אבל זה לא נכון!
עכ"פ שתי השגיאות לדעתי קשורים לזה שיש יותר מAddress אחד, ואילו אתה מתייחס רק לראשון. אז ממה נפשך, אם זה אותו קונטקסט, אז יש בעיה של ניסיון שינוי הID (כי נעשה בו שינויים ע"י הMAP - הוא כנראה במצע SET גם למאפיינים זהים) ואם זה קונקסט חדש, הרי זה נחשב EntityState.Added, בעוד יש להם כבר ID קיים ולכן נעשה נסיון לשים איבר כפול בDB (ואם לא ביטלת את הישן יש גם בעיה של שתי קונטקסטים לאותו אלמנט).
אם אתה רוצה לעשות נכון, תעיף את יצירה של הקונטסט החדש, ותוסיך גם לולאה לAddress
כלומר תכניס לפני שורה 14 (בקוד המקורי שהבאת בהודעה הפותחת) את הלולאה הזו:foreach (var a in donor.Addresses) db.Entry(a).State = EntityState.Unchanged;
עם איזה מחלקת mapper אתה משתמש?
ושאלה שממש בוערת במקרה הזה, איך הmapper יודע מה שורה קיימת ומה חדשה בליסטים של הכתובות והקטגוריות??פורסם במקור בפורום CODE613 ב14/11/2017 09:42 (+02:00)
-
@דוד ל.ט.
אם אתה רוצה לעשות נכון, תעיף את יצירה של הקונטסט החדש, ותוסיך גם לולאה לAddress
כלומר תכניס לפני שורה 14 (בקוד המקורי שהבאת בהודעה הפותחת) את הלולאה הזו:foreach (var a in donor.Addresses) db.Entry(a).State = EntityState.Unchanged;
אז לא... זה לא עובד :?
נותן עדיין את אותה השגיאה, למרות שאפי' הוספתי במחלקות של הDAL את האטריביוט[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
רק הדרך העקומה שלי עובדת משום מה..
זה נשמע לי כמו באג באנטיטי..פורסם במקור בפורום CODE613 ב14/11/2017 20:23 (+02:00)
-
זה נשמע לי כמו באג באנטיטי..
אתה כתבת את זה ברצינות?
@דוד ל.ט.המילה באג נאמרת לדעתי ברוב המקרים כתירוץ לאי לקיחת אחריות על בעיה שלא מוצאים לה שורש (כתבתי על זה פה http://tchumim.com/post/8965).
תענה לי בקשר לmapper. כי החשד נופל עליו.
כמו"כ לפי החשבון שלי, גם הדרך שלך שעובדת היא לא עושה את העבודה בDB כמו שצריך, בדוק את זה.פורסם במקור בפורום CODE613 ב14/11/2017 20:31 (+02:00)
-
הDB הוא סטטי למחלקה, והפונקציה סטטית, ואני לא מאתחל אותו בכל קריאה.
public static class MapObjToUI { static Model db = new Model();
כנ"ל הmapper הוא משתנה סטטי, של המחלקה:
static MapperConfiguration config = new MapperConfiguration(cfg => { cfg.CreateMap<Donor, DonorVM>(); cfg.CreateMap<Address, ContactAddressVM>(); cfg.CreateMap<Category, CategoryVM>(); cfg.CreateMap<Communication, CommunicationVM>(); cfg.CreateMap<Setting, SettingVM>(); });
פורסם במקור בפורום CODE613 ב14/11/2017 21:34 (+02:00)
-
סטטי לDbContext ועוד בווב זה רעיון גרוע מאוד. אין ספק שהבעיה נעוצה בזה.
אם אין לך כח להצהיר (כשזה כמה וכמה מתודות), תצהיר ברמת הקונטרולר [u:wv98m2jv]לא סטטי[/u:wv98m2jv], ותממש בקונטרולר IDispsable ובמתודת Dispose תסגור את המופע של הקונטקסט.
להגיד שהבנתי את השגיאה? לא לגמרי.פורסם במקור בפורום CODE613 ב14/11/2017 21:54 (+02:00)
-
@דוד ל.ט.
סטטי לDbContext ועוד בווב זה רעיון גרוע מאוד. אין ספק שהבעיה נעוצה בזה.
אם אין לך כח להצהיר (כשזה כמה וכמה מתודות), תצהיר ברמת הקונטרולר [u:23k0yp2q]לא סטטי[/u:23k0yp2q], ותממש בקונטרולר IDispsable ובמתודת Dispose תסגור את המופע של הקונטקסט.
להגיד שהבנתי את השגיאה? לא לגמרי.מזל שיש אותך!!
שיניתי.. אבל זה עדיין זורק את אותה השגיאה <!-- s:-) --><img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":-)" title="מחייך" /><!-- s:-) -->פורסם במקור בפורום CODE613 ב14/11/2017 21:57 (+02:00)
-
@דוד ל.ט.
סטטי לDbContext ועוד בווב זה רעיון גרוע מאוד. אין ספק שהבעיה נעוצה בזה.אם אין לך כח להצהיר (כשזה כמה וכמה מתודות), תצהיר ברמת הקונטרולר [u:3s3pc33d]לא סטטי[/u:3s3pc33d], ותממש בקונטרולר IDispsable ובמתודת Dispose תסגור את המופע של הקונטקסט.
להגיד שהבנתי את השגיאה? לא לגמרי.מזל שיש אותך!!
שיניתי.. אבל זה עדיין זורק את אותה השגיאה <!-- s:-) --><img src="{SMILIES_PATH}/icon_e_smile.gif" alt=":-)" title="מחייך" /><!-- s:-) -->טוב כעת תורך לענות על השאלות האחרות.
פורסם במקור בפורום CODE613 ב14/11/2017 21:58 (+02:00)
-
טוב, אז כפי שדוד העריך הבעיה היא בשילוב של הmapper (במקרה שלנו השתמשתי בספרייה automapper) עם הORM - דהיינו ה entityframework.
מכיון שכאשר אני ממפה את האובייקטים שקיבלתי מהUI לאובייקטים של שכבת הדטה, והאובייקט שלי מכיל אובייקטים מקוננים (כגון ליסטים של הקטגוריות, כתובות ואמצעי תקשורת), המפר יוצר לי אובייקטים חדשים, והוא לא מעדכן את האובייקטים הקיימים. ממילא, הORM לא יודע אם זה אובייקט חדש או שאני מוסיף אובייקטים והוא זורק את השגיאה, שכבר קיים אוביקט עם המזהה הזה.
בקישור הנ"ל יש מאמר נפלא בנוגע בדיוק לבעיה הזאת, והוא ממליץ לא להשתמש בmapper במצבים כאלה, אלא למפות את האובייקטים בעצמך, וזה אכן מה שעשיתי, ופתר לי את הבעיות.
תודה לדוד על העזרה!
פורסם במקור בפורום CODE613 ב14/11/2017 23:32 (+02:00)