Wpadłem w pułapkę relacji wiele do wielu, m:n. Po raz kolejny. Jak fretka w sidła… te same po raz n-ty (czy m-ty?). Byłem na siebie tak wściekły, że to ludzkie pojęcie przechodzi. Właściwie bardziej mi teraz szkoda nerwów niż straconego czasu.
Ale o co się, panie, rozchodzi?
W moim systemie miałem bardzo prostą zależność: Company (n) – (m) Customer. Firma posiada wielu klientów, a klient przypisany jest do wielu firm. Bez dodatkowych ceregieli utworzyłem:
1: public class Company 2: { 3: public virtual ICollection<Customer> Customers { get; set; } 4: // ... 5: } 6: 7: public class Customer 8: { 9: public virtual ICollection<Company> Companies { get; set; } 10: // ... 11: }
WIEDZIAŁEM że coś jest nie tak. Już dawno, dawno temu obiecałem sobie, że nigdy nie dopuszczę do takiej sytuacji. Sytuacji, którą nazwałbym "implicit/direct many to many relation" – może niekoniecznie poprawnie. Pozostawienie takiej zależności jest proszeniem się o kłopoty. Samoograniczenie do potęgi N.
Mimo tego, że zdawałem sobie sprawę z wad powyższego rozwiązania, nie uporałem się z nim natychmiast. Zamiast tego pomyślałem "e tam, zobaczymy jak to się rozwinie, może będzie dobrze". Pomyślałem tak sobie wiele razy, co kilka dni.
Gdybym zaradził temu od razu, poświęciłbym całemu zadaniu wprowadzenia dodatkowej klasy reprezentującej relację pomiędzy klientem a firmą raptem godzinkę, może dwie. Jednak wszystko strzeliło dopiero dwa miesiące później, gdy pojawiło się wymaganie:
"Chciałbym wiedzieć kiedy klient został skojarzony z firmą; dodatkowo klient może mieć pewne preferencje dotyczące firm, każdej z osobna; przydałaby się również informacja kto klienta do firmy przypisał"
Dodanie klasy:
1: public class CompanyCustomerAssociation 2: { 3: public virtual Company Company { get; set; } 4: public virtual Customer Customer { get; set; } 5: public virtual DateTime CreationDate { get; set; } 6: // ... 7: }
nie było już wtedy tak banalne. Gdy po dobrej godzinie czy półtorej udało mi się skompilować projekt – posypało się prawie 150 testów. Poprawienie całego kodu zajęło mi kolejne 6 czy 7 godzin. Ręczne testy (tak dla całkowitej pewności…) – kolejne 2 godziny.
A to wszystko przez… no właśnie, nie wiem przez co. Chyba pozostaje jedynie określenie GŁUPOTA. Od samego początku wiedziałem, że robię źle. Od samego początku wiedziałem, że wcześniej już się nadziałem na ten bolec. Ignorując zdobyte w równie bolesny sposób doświadczenie postąpiłem tak, jakbym wcześniej nie był w takiej sytuacji i się przy tej okazji nie sparzył.
Ale dosyć tego, to był ostatni raz. Od tego dnia relacje m:n dla mnie nie istnieją. ZAWSZE będę jawnie tworzył obiekt łączący encje w ten sposób. Może się przyda, a może nie… w bazie danych i tak musi występować dodatkowa tabela.
Another lesson re-learned,
Procent, the Moron King