Radomił Ząbik 308 Napisano 24 Stycznia 2022 Udostępnij Napisano 24 Stycznia 2022 w [Sfera] Usuwanie pozycji z cenników dodatkowych "OutOfMemory" Mam w rozwiązaniu sferycznym jedną funkcję, która tworzy dodatkowy asortyment, a właściwie usługę, na podstawie innego asortymentu. Częścią tego procesu, jest usunięcie zbędnych informacji związanych z asortymentem, między innymi wywalenie go z cenników dodatkowych, jeśli się znajduje. Robię to takim kodem: foreach (Cennik dodatkowy in usluga.Dane.PozycjeCennika.Select(p => p.Cennik).Distinct()) { ICennik dodatkowyBo = cenniki.Znajdz(dodatkowy); foreach (IUproszczonaPozycjaCennika uprPozCen in dodatkowyBo.Pozycje.Wszystkie.Where(p => p.IdAsortymentu == usluga.Dane.Id)) dodatkowyBo.Pozycje.Usun(uprPozCen); if(!dodatkowyBo.Zapisz()) dodatkowyBo.WypiszBledy(); } Dzisiaj, dostałem taki oto błąd: System.OutOfMemoryException: Zgłoszono wyjątek typu 'System.OutOfMemoryException'. w lambda_method(Closure , Shaper ) w System.Data.Entity.Core.Common.Internal.Materialization.Coordinator`1.ReadNextElement(Shaper shaper) w System.Data.Entity.Core.Common.Internal.Materialization.Shaper`1.SimpleEnumerator.MoveNext() w System.Data.Entity.Internal.LazyEnumerator`1.MoveNext() w System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) w System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source) w InsERT.Moria.CennikiICeny.KoordynatorUproszczonychPozycjiCennika.UtworzUproszczonePozycjeInternal(IQueryable`1 query) w InsERT.Moria.CennikiICeny.KoordynatorUproszczonychPozycjiCennika.UtworzUproszczonePozycje(IQueryable`1 query) w InsERT.Moria.Narzedzia.KoordynatorUproszczonychPozycji`4.PodajPozycje() w InsERT.Moria.CennikiICeny.CennikBO.InsERT.Moria.CennikiICeny.ICennikPozycje.get_Wszystkie() w SynchronousSocketListener.StartListening() Całkiem możliwe, że wczytywanie takie zakresu danych sprawia problem dla pamięci, bo mamy sporo produktów, przewinęło się też sporo cenników. Metoda była skonstruowana w sumie w 2017 roku, na podstawie tego postu: W międzyczasie, cenniki się zmieniły, więc może można to zrobić lepiej? Link to postu
Wojciech Szopiński 226 Napisano 25 Stycznia 2022 Udostępnij Napisano 25 Stycznia 2022 w [Sfera] Usuwanie pozycji z cenników dodatkowych "OutOfMemory" Po pierwsze brakuje tam using'a więc po zapisie każdego obiektu "dodatkowyBO" nie są zwalniane zasoby przez niego zajęte. Po drugie warto byłoby w tej pętli odfiltrować TYLKO cenniki dodatkowe (na podstawie pola Bazowy encji Cennik). W tym przypadku dla cenników głównych nadmiarowo będzie wykonywana operacja usuwająca pozycje, która i tak nie ma szans zadziałać (cennik główny musi mieć wszystkie pozycje z kartoteki). Po trzecie zamiast ładować wszystkie uproszczone pozycje można wykorzystać metodę ICennikPozycje.ZnajdzPozycjeCennika(Asortyment asortyment), która pobierze nam TYLKO pozycje związane z podanym asortymentem. Ewentualnie można byłoby spróbować zamiast ładować cały cennik wykorzystać menedżer pozycji cennika (IPozycjeCennika) załadować interesujące nas pozycje (IPozycjaCennika) i je usunąć omijając w ogóle obiekt biznesowy cennika (ICennik), ale to wymagałoby już większej przeróbki tego kodu. Link to postu
Radomił Ząbik 308 Napisano 25 Stycznia 2022 Autor Udostępnij Napisano 25 Stycznia 2022 w [Sfera] Usuwanie pozycji z cenników dodatkowych "OutOfMemory" No dobra, to zobaczymy, czy dobrze załapałem sugestie 4 godziny temu, Wojciech Szopiński napisał: Po pierwsze brakuje tam using'a więc po zapisie każdego obiektu "dodatkowyBO" nie są zwalniane zasoby przez niego zajęte. using(ICennik dodatkowyBo = cenniki.Znajdz(dodatkowy)) 4 godziny temu, Wojciech Szopiński napisał: Po drugie warto byłoby w tej pętli odfiltrować TYLKO cenniki dodatkowe (na podstawie pola Bazowy encji Cennik). foreach (Cennik dodatkowy in usluga.Dane.PozycjeCennika.Select(p => p.Cennik).Distinct().Where(c => c.Bazowy == false)) 4 godziny temu, Wojciech Szopiński napisał: Po trzecie zamiast ładować wszystkie uproszczone pozycje można wykorzystać metodę ICennikPozycje.ZnajdzPozycjeCennika(Asortyment asortyment), która pobierze nam TYLKO pozycje związane z podanym asortymentem. ICennikPozycje pozycjeCennika = dodatkowyBo.Pozycje; var uslugaDoUsuniecia = asortymenty.Dane.Wszystkie().Where(a => a.Id == usluga.Dane.Id).FirstOrDefault(); foreach(var pozycja in pozycjeCennika.ZnajdzPozycjeCennika(uslugaDoUsuniecia)) dodatkowyBo.Pozycje.Usun(pozycja); Swoją drogą, szkoda, że WypelnijNaPodstawie dla asortymentu, nie może pominąć kopiowania cenników, bo usuwanie tych pozycji z cennika trwa bardzo długo. Dlatego też w ostatecznej wersji Swojego kodu, pominąłem cenniki, które są zamknięte - ryzyko ponownego otwarcia w mojej organizacji jest znikome, więc można zaryzykować. Ostatecznie, kod wygląda tak - jest ok (to wtedy wrzucę nową wersję do tamtego postu, może komuś pomoże). foreach (Cennik dodatkowy in usluga.Dane.PozycjeCennika.Select(p => p.Cennik).Distinct().Where(c => c.Bazowy == false && c.Status != 2)) { using(ICennik dodatkowyBo = cenniki.Znajdz(dodatkowy)) { Console.WriteLine("Cennik: "+dodatkowyBo.Dane.Tytul); ICennikPozycje pozycjeCennika = dodatkowyBo.Pozycje; var uslugaDoUsuniecia = asortymenty.Dane.Wszystkie().Where(a => a.Id == usluga.Dane.Id).FirstOrDefault(); foreach(var pozycja in pozycjeCennika.ZnajdzPozycjeCennika(uslugaDoUsuniecia)) { Console.WriteLine("Usuwanie pozycji: "+pozycja.Id+"/"+pozycja.CenaBazowa); dodatkowyBo.Pozycje.Usun(pozycja); } if(!dodatkowyBo.Zapisz()) dodatkowyBo.WypiszBledy(); } } Link to postu
Polecane posty