elasticsearch i docker

Update, Attach, SaveChanges i inne składniki EntityFrameworka

Wprowadzenie

Pracując z Entity Framework możemy doceniać jego moc oraz zapomnieć o tym, jaką potężną magią on operuje. Np. skąd ten diabeł wie, co się zmieniło, a kiedy muszę mu o tym przypomnieć.

Mam prostą regułę w głowie, jeśli wyciągam dane z kontekstu i zaraz od razu wrzucam je tam z powrotem, nie ustawiam do tego flag, nie wtrącam się, nie robię hokus-pokus i zakładam, że wszystko będzie dobrze.

Jeśli wyciągam dane na dłużej, wtedy podpowiadam EF, żeby nie śledził zmian, bo to trochę zajmie, zanim te dane wrócą do bazy danych i szkoda zachodu.

Dane można zapisać / zaktualizować na kilka sposobów:

Na raz:

  • Pobierz
  • Zmodyfikuj
  • Zapisz

Na dwa

  • Utwórz
  • Przypnij
  • Zapisz

Na trzy:

  • Nie zaglądam, jeśli działa u Ciebie to dawaj dawaj na produkcje 😉

Wygląda że proste? To sprawdzam, co i jak zadziała

W obu przypadkach mam taki oto kod:

Nie oszukujmy się, bunkrów nie ma, kontekst oraz jakiś POCO na potrzeby przykładów.

Uno

Ten przykład działa, pobieram, modyfikuje, zapisuje. EF robi magię i potrafi sam wykryć zmianę w encji – nie wymaga wywołania `update` aby znaleźć i nanieść zmiany na obiekcie. PFM! Wymagany jest natomiast strzał do bazy aby pobrać początkowy obiekt do modyfikacji.
Na plus – nie tracę informacji, który nie modyfikuje. Wrócę do tego niżej.

Duo(s)

Teraz się zacznie, co się stanie, gdy wyciągnę dane bez śledzenia i zapiszę zamiany:

Pudło! Nic, EF cichutko “zapisał” zmienione encje, ale mój odcięty obiekt nie był na tej liście, w związku z tym – nic się nie wydarzyło. Może tylko odrobina smutku. Ale sam tego chciałem, przecież mówiłem – bez śledzenia!

Spróbuje inaczej, stworze nowy obiekt, przypnę go do kontekstu i wtedy zapisze:

Hus! (Dzięki panie Łukaszu) – nie działa! Ale czemu? Przecież obiekt jest w kontekście!

Ach, obiekt został dodany, ale jest oznaczony jako unchanged! Ok-sprawdzam:

Czyli co, nawet jeśli mam nowy obiekt i przypiąłem go do kontekstu nadal nie jest śledzony? Nie koniecznie, obiekt został przypięty i jest śledzony, ale zmiany nie nastąpiły po włączeniu śledzenia. Natomiast taki kod:

Robi już robotę, zwróć uwagę, że zmiany następują po przypięci i włączeniu śledzenia zmian

Zamiast takiego cyrkolenia się, można iść na skróty i wywołać po prostu Update:

Który ustawia status obiektu na modified i zapisuje zmiany.

Turbo mega uwaga:
Oba przypadku zerują wartość dla ReleaseDate który dostanie domyślną 01.01.0001 00:00:00 wartość-trzeba tego pilnować. W przypadku gdy wcześniej ładujemy obiekt z DB a potem go modyfikujemy, ReleaseDate jest ustawiony i nie nadpisany zerową wartością.
Pewnie można by poszukać i podpowiedzieć, które właściwości zostały zmienione, ale to wymagałoby znajomości voodoo.

Dodam tylko dla optymalizacji, że gdy wyciągamy obiekt z EF, który nie będzie zmieniany, np. tylko żeby wyciągnąć i wyświetlić, warto użyć opcji `
AsNoTracking, aby podpowiedzieć EF zaprzestania śledzenia obiektów, bo zniknąć one z naszego kontekstu.

Jeśli zaistnieje potrzeba ponownego podpięcia, można zrobić attach lub update – ale to już wiesz.

 

Szczegóły tutej:
https://learn.microsoft.com/en-us/ef/core/change-tracking/

ps.
Tak naprawdę to nie korzystam z EF.

ps2.
Źródło całego pliku cs dostępne tutaj:
https://gist.github.com/jstadnicki/9a97619c26e4ba9571fa2aec40be25d3

Logowanie dla leniwych

Nie lubię logowania

Nie lubię logowania — brudzi mi w kodzie; narzekam, gdy podczas ratowania produkcji brak logów — jak żyć?!

Jestem leniwy, nie lubię pamiętać o tym i tamtym — lubię, gdy rzeczy dzieją się same i nie muszę sobie zawracać tym głowy. Ale bez przesady! Logi to najgorsze i najlepsze co może spotkać programistów — z jednej strony logi zaśmiecają kod, z drugiej strony dają podgląd na to, co użytkownicy wymyślili na produkcji.

AOP

Logowanie przy pomocy AOP oczyszcza kod w przypadku typowego i klasycznego podejścia do logów, ok — może to zrobić. Często szukam w logach tego, co zostało uruchomione i z jakim parametrem, aby zrozumieć, co poszło nie tak. Nie lubię ^C^V takiego kodu na początku każdej metody. Niestety nie znalazłem dobrego rozwiązania AOP (czytaj darmowego) a interfejs IIntercept z jakiegoś powodu nie chce zostać uruchomiony (ale jest tworzony — kiedyś to zrozumiem); z tego powodu przy pomocy internetów znalazłem DispatchProxy które świetnie robi swoją robotę.

DispatchProxy

Otóż chciałbym mieć możliwość logowania tego, co i jak się wywołuje z możliwością włączenia / wyłączenia detali (poziomy logowania w moim przypadku, lub inna forma konfiguracji). Chce móc przeczytać logi i dowiedzieć się co się wywołuje i z jakim parametrami, dla każdej metody, dodatkowo bez potrzeby modyfikacji kodu, gdy dana metoda się zmieni.

Można to zrobić przy pomocy DispatchProxy które przechwyci wywołanie metody i umożliwi wykonanie dowolnego kodu; przed; po czy też podczas błędu.

Otóż taka klasa opina ładnie swoją docelową klasę T , a następnie podczas tworzenia zwraca takie proxy, udając klasę typu podstawowego. Tutaj uwaga: konstruktor musi być pusty, a ewentualne przekazanie parametrów i ich  przypisanie następuje w metody fabrykującej (wewnątrz if)

Gdy użytkownik takiej klasy wywołuje metodę docelową, na proxy wcześniej zostanie zawołane Invoke gdzie można czynić cuda.
Ja na przykład na poziomie `Information` loguje nazwę wywoływanej metody, a na poziomie Debug dorzucam także nazwy i wartości przekazanych argumentów.

Rejestracja

Piękne jest to, że DispatchProxy nie wymaga zewnętrznych bibliotek i działa na czysto z .net. Zależność do klasy rejestruje w taki sposób:

Akcja

Działa to tak:

Tutaj przykład konsumpcji oraz wykorzystania przykładowego serwisu

A tutaj logi:

Serwis jest nudny do bólu i prawie o nim zapomniałem:

Siup

W tak przygotowanym kodzie, zależności rejestrowane z pomocą logera powinny samodzielnie wrzucać informację o tym, co i jak się wykonało. Oczywiście można dodać sobie flagi do optymalizacji tego, czy przed, czy po co w sytuacjach wyjątkowych ma się logować i na jakim poziomie. Warto także pomyśleć o tym, jak takie logi ze sobą łączyć za pomocy correlationId – ale to pozostawiam już waszej wyobraźni.

 

ps.
dzisiaj bez obrazka

Zaślepić HttpClient

Zajawnik / Reklama

Testy jednostkowe to dobra sprawa – to oczywista oczywistość. Można o nich sporo pisać, można zobaczyć też co ja o nich piszę/mówie na udemy (https://www.udemy.com/course/wprowadzenie-do-testowania-dla-programistow-net/learn/lecture/13612678#overview) albo na kursy.jaroslawstadnicki.pl.

Czasem jednak chce się więcej, to że testy są na zielono nie oznacza jeszcze, że wszytko działa.

Tylko w ruscie, jak się skompilowało to można na proda wrzucać 😉

Integrować się chce

No ale ale, chce napisać, że marzy mi się taka sytuacja, że mogę sobie odpalić i szybko przetestować cały kod (prawie cały) od wejścia do zapisu. Większość rzeczy, z którymi pracuje, albo zaczyna się na http, albo kończy się na http, a ja nie chce nigdzie strzelać, chce to zaślepić i mieć pod kontrolą — jak?!

Continue reading

tu ma być spacja

Zamarudziłem ostatnio na twiterze, że przestałem lubić code review:

To nie pierwszy raz, kiedy marudzę, nie pierwszy raz, kiedy na Twitterze i nie pierwszy raz o tym, że komentarze na temat spacji, wcięć, klamerek i całej serii białych znaków to czyste 💩

Ile jeszcze? Otóż dorosłem 👴 i chce coś z tym zrobić. Można na różne sposoby, ja wybrałem .editorconfig – bo jest wspierany z pudełka przez większość edytorów

Oczywiście moje życie mówi sprawdzam! i jest trochę inaczej, ale ostatecznie można to ogarnąć.

Continue reading