Relacje mają konsekwencje
Dostępne także w 28 językach
English · Español · 日本語 · Português (Brasil) · Français · Deutsch · Italiano · 한국어 · 简体中文 · Português (Portugal) · 繁體中文 · Bahasa Indonesia · Türkçe · Tiếng Việt · ไทย · Nederlands · العربية · עברית · Українська · हिन्दी · Русский · Svenska · Dansk · Norsk bokmål · Suomi · Español (México) · Français (Canada) · Deutsch (Schweiz)

Moduł 7 z 10 w rozdziale Architektura danych Salesforce, rozdziale 3 kursu Data Architect. Każdy moduł jest samodzielny. Wstecz: Pola to też architektura · Dalej: Własność i cykl życia
Pytanie, na które odpowiada ten moduł: co naprawdę wybieram, łącząc dwa obiekty Salesforce?
Narysowanie relacji jest łatwe. W rozdziale 2 rysowaliśmy linie i je nazywaliśmy: partner detaliczny wysyła wiele manifestów, dostawa zawiera wiele pozycji, ekipy i ciężarówki spotykają się w przydziale ekipy. Mówiliśmy o liczności, opcjonalności i historii. Teraz implementujemy te linie w Salesforce, a linia na diagramie zaczyna nieść dużo większy ciężar.
Wybierając typ relacji w Salesforce, nie mówię tylko, że te dwa rekordy są połączone. Mogę też decydować, kto jest właścicielem rekordu podrzędnego, czy może istnieć bez rodzica, kto może go widzieć, co się dzieje po usunięciu rodzica, czy może przejść do innego rodzica, czy mogę go podsumować na rodzicu i co się dzieje, gdy rekordów podrzędnych są setki tysięcy. Relacja to nie tylko linia. Niesie zachowanie.
Zacznij od relacji biznesowej
Dział zatytułowany „Zacznij od relacji biznesowej ”Zanim przejdziesz do lookup czy master-detail, wróć do biznesu. Weźmy dostawę i jej pozycje: lodówkę, instalację, wywóz. Czy pozycja może istnieć bez swojej dostawy? Nie. Jeśli dostawa zostanie usunięta, czy jej pozycje też powinny zniknąć? Tak. Czy pozycje potrzebują własnego właściciela albo własnych zabezpieczeń? Właściwie nie. Czy ktoś powinien przenosić pozycję z jednej dostawy do drugiej? Miejmy nadzieję, że nie przypadkiem.
Teraz weźmy dostawę i trasę, na której jest. Dostawa istnieje, zanim trafi na trasę, może zostać przeniesiona na inną trasę, gdy zmienia się plan, a usunięcie trasy nigdy nie powinno usuwać dostaw na niej. Dwie linie jeden-do-wielu, które na diagramie wyglądają tak samo, a zachowują się zupełnie inaczej. Zwróć uwagę, że wciąż nie powiedzieliśmy „lookup” ani „master-detail”. Najpierw opisz zachowanie. Konfiguracja je implementuje.
Typy relacji
Dział zatytułowany „Typy relacji ”Otwórz ekran Nowe pole, a Salesforce zaproponuje ci garść typów relacji (Object Relationships Overview (opens in a new tab), po angielsku):
- Lookup (relacja wyszukiwania): łączy dwa obiekty. Chleb powszedni relacji w Salesforce.
- Master-detail (nadrzędny-szczegółowy): wiązanie rodzic-dziecko, w którym rodzic kontroluje rekord podrzędny.
- Wiele-do-wielu: nie osobny typ pola, ale wzorzec: obiekt łączący Salesforce (Salesforce Junction Object), czyli obiekt niestandardowy z dwiema relacjami master-detail.
- Relacja do samego siebie (self-relationship): lookup z obiektu do niego samego.
- Hierarchiczna: specjalny lookup, który istnieje tylko na obiekcie User, na przykład przełożony użytkownika.
- Zewnętrzny lookup (external lookup) i pośredni lookup (indirect lookup): relacje do obiektów zewnętrznych i z nich, czyli obiektów
__xz modułu 4. Zewnętrzny lookup wskazuje na nadrzędny obiekt zewnętrzny; pośredni lookup wskazuje z obiektu zewnętrznego na obiekt standardowy lub niestandardowy, dopasowując po unikalnym External ID.
Większość czasu projektowania idzie na pierwsze trzy. Weźmy je po kolei.
Lookup: te rekordy są połączone
Dział zatytułowany „Lookup: te rekordy są połączone ”Lookup mówi: ten rekord jest powiązany z tamtym rekordem. Rekord podrzędny zachowuje własną tożsamość, własnego właściciela i własne życie. Dostawa wskazuje na swoją trasę. Jeśli trasa zostanie anulowana, dostawy nie znikają; wracają do ponownego planowania tras.
To zabawne: pole lookup trafia na rekord podrzędny, ale rodzic też coś dostaje: listę powiązaną (related list) swoich dzieci. Tworząc lookup, nazwij więc oba końce. Related List Label to to, co ludzie widzą na rodzicu, a Child Relationship Name to to, czego programiści i integracje używają, żeby przejść od rodzica do dzieci. Nie akceptuj wartości domyślnych.
Lookup może być wymagany albo opcjonalny. Gdy jest opcjonalny, decydujesz, co się stanie, jeśli rekord, na który wskazuje, zostanie usunięty, i są trzy możliwości (Considerations for Object Relationships (opens in a new tab), po angielsku):
- Clear the value of this field (wyczyść wartość tego pola), domyślnie. Rekord podrzędny zostaje, z pustym lookupem.
- Don’t allow deletion (nie pozwalaj na usunięcie) rekordu wskazywanego. Spróbuj usunąć trasę, a Salesforce odmówi: jest częścią relacji.
- Delete this record also (usuń także ten rekord), czyli usuwanie kaskadowe, jak w master-detail. Ta opcja jest dostępna tylko dla niestandardowego lookupu na obiekcie niestandardowym, jest domyślnie wyłączona i Salesforce musi ją włączyć dla twojego orgu, bo usuwanie kaskadowe omija zabezpieczenia i udostępnianie: użytkownicy mogą usunąć rekordy, których nawet nie widzieli.
To decyzja o cyklu życia ukryta na ekranie konfiguracji.
Filtry lookupu (lookup filters) zawężają to, co użytkownik może wybrać. Powiedzmy, że dostawa ma lookup Installer do kontaktu, a instalatorzy to jeden typ rekordu kontaktu spośród wielu. Filtr lookupu pokazuje tylko instalatorów i może filtrować według bieżącego rekordu, według wyszukiwanego rekordu i według użytkownika: jego profilu, roli albo uprawnień (Lookup Filters (opens in a new tab), po angielsku). To tani sposób, żeby lookup był uczciwy.
Master-detail: ten rekord podrzędny należy do tamtego rodzica
Dział zatytułowany „Master-detail: ten rekord podrzędny należy do tamtego rodzica ”Master-detail składa dużo mocniejszą deklarację. Na zajęciach nazywam to bardzo ścisłym wiązaniem. Nie możesz mieć rekordu szczegółowego bez nadrzędnego; pole nadrzędne jest wymagane. Rekord szczegółowy traci własne pole Właściciel i dziedziczy właściciela rodzica. Nie ma osobnej tabeli udostępniania dla rekordu szczegółowego, więc nie możesz udostępnić go osobno; dziedziczy udostępnianie rodzica. Dlatego obiekt szczegółowy nie może mieć reguł udostępniania, udostępniania ręcznego ani kolejek: wszystkie potrzebują pola Właściciel (Object Relationships Overview (opens in a new tab), po angielsku). W Konfiguracji jego ustawienie udostępniania brzmi Controlled by Parent (kontrolowane przez rodzica). A w samym polu master-detail wybierasz Sharing Setting (ustawienie udostępniania): czy użytkownik potrzebuje dostępu Read Only czy Read/Write do rekordu nadrzędnego, żeby tworzyć, edytować albo usuwać jego rekordy szczegółowe. Usunięcie rekordu nadrzędnego usuwa jego rekordy szczegółowe. A rekord nadrzędny dostaje pola podsumowania zbiorczego (roll-up summary).
Jeśli więc pozycja dostawy jest rekordem szczegółowym dostawy, mówię: ta pozycja należy do tej dostawy przez całe swoje życie. Na to pytanie chcę znać odpowiedź, zanim ktokolwiek wybierze w Konfiguracji relację master-detail.
Pytanie o usuwanie
Dział zatytułowany „Pytanie o usuwanie ”Oto mój ulubiony sposób sprawdzenia, czy wszystko przemyśleliśmy: co powinno stać się z rekordami podrzędnymi, jeśli ktoś usunie rodzica? Wszyscy robią się niespokojni. Dobrze. Teraz uprawiamy architekturę.
Partner detaliczny ma setki tysięcy historycznych dostaw. Ktoś usuwa partnera. Czy dostawy powinny zniknąć? Niemal na pewno nie: zależą od nich reklamacje, rozliczenia i historia. Może usuwanie partnera w ogóle nie powinno być dozwolone, a partnera należy dezaktywować. W master-detail usunięcie rekordu nadrzędnego kaskadowo usuwa rekordy szczegółowe i ich rekordy szczegółowe; przywrócenie rekordu nadrzędnego je przywraca (Considerations for Object Relationships (opens in a new tab), po angielsku). Kiedy więc ktoś mówi „master-detail daje nam roll-upy”, odpowiadam: świetnie. Na co jeszcze właśnie się zgodziliśmy?
Własność jedzie w pakiecie
Dział zatytułowany „Własność jedzie w pakiecie ”W lookup rekord podrzędny może mieć własnego właściciela. W master-detail nie może; dostęp wynika z rekordu nadrzędnego. To dokładnie właściwe, jeśli rekord szczegółowy naprawdę jest częścią rodzica. Ale jeśli rekord podrzędny potrzebuje własnego właściciela, własnego udostępniania albo własnego cyklu życia, model mówi ci, że master-detail to zły wybór. Następny moduł wchodzi głębiej we własność, a kurs Sharing and Visibility jeszcze dalej. Na razie: projekt relacji i projekt bezpieczeństwa to nie osobne rozmowy. Model danych kształtuje model bezpieczeństwa, zanim ktokolwiek napisze regułę udostępniania.
Rodzic wymagany czy opcjonalny?
Dział zatytułowany „Rodzic wymagany czy opcjonalny? ”Czy rekord podrzędny może istnieć, zanim poznamy jego rodzica? To ważniejsze, niż się wydaje. Jeśli dostawy przychodzą w manifeście wieczorem poprzedniego dnia, a trasy buduje się potem, wymagana trasa na dostawie oznaczałaby, że planowanie tras musi nastąpić, zanim rekord w ogóle da się utworzyć. Relacja fizyczna musi obsługiwać prawdziwy cykl życia. Nie projektuję więc relacji wyłącznie na podstawie statycznego diagramu. Chcę wiedzieć: jak rekordy się rodzą, czy mogą istnieć same, czy mogą się przenosić i jak umierają?
Czy rekord podrzędny może zmienić rodzica?
Dział zatytułowany „Czy rekord podrzędny może zmienić rodzica? ”Domyślnie rekordu podrzędnego w master-detail nie można przenieść do innego rodzica. Można na to pozwolić, zaznaczając w relacji Zezwalaj na zmianę rekordu nadrzędnego (Allow reparenting) (Considerations for Object Relationships (opens in a new tab), po angielsku). Mój instynkt jest zachowawczy: jeśli biznes mówi, że rekord podrzędny należy do jednego rodzica na całe życie, nie ułatwiam przenoszenia. Przejście pozycji z jednej dostawy do drugiej powinno być świadomym zdarzeniem biznesowym, a nie edycją pola. I znowu: ustawienie to nie architektura. Architekturą jest reguła cyklu życia, a ustawienie ją implementuje.
Dwie kolejne rzeczy, które później zaskakują zespoły. Nie da się utworzyć relacji master-detail na obiekcie, który już ma dane; tworzy się lookup, wypełnia go w każdym rekordzie, a potem konwertuje. A z powrotem na lookup da się przejść tylko wtedy, gdy na rekordzie nadrzędnym nie ma pól podsumowania zbiorczego. Zobacz też, co konwersja robi z bezpieczeństwem: zamiana lookupu w master-detail ustawia udostępnianie rekordu podrzędnego na Controlled by Parent, a zamiana master-detail z powrotem w lookup ustawia domyślne ustawienie dla całej organizacji (organization-wide default) rekordu podrzędnego na Public Read/Write (Considerations for Object Relationships (opens in a new tab), po angielsku). Rekordy, które wczoraj były prywatne, dziś są otwarte, dopóki ktoś tego nie zauważy. Wybierz wcześnie.
Roll-upy są przydatne, ale nie za darmo
Dział zatytułowany „Roll-upy są przydatne, ale nie za darmo ”Lubię roll-upy. Policz pozycje dostawy, zsumuj kwoty pozycji faktury, znajdź najpóźniejszą datę: natywnie, bez kodu. Pole master-detail trafia na rekord podrzędny, ale roll-up trafia na rodzica. Mają jednak drobny druk (Roll-Up Summary Field (opens in a new tab), po angielsku):
- Przeliczenie wartości roll-up po pewnych zmianach (nowe pole roll-up, zmieniona formuła, od której zależy, wymuszone przeliczenie) może trwać do 30 minut, zależnie od liczby objętych rekordów. Widziałem, jak ludzie zastanawiali się, dlaczego liczba na rodzicu jeszcze się nie zmieniła.
- Nie da się podsumować wszystkiego. Autonumer nie może być polem, które agregujesz. A roll-up może podsumować pole formuły tylko wtedy, gdy ta formuła nie sięga do innego obiektu i nie używa funkcji, która zmienia się sama, takiej jak
NOW()czyTODAY(). Formuła „dni po terminie” oparta naTODAY()zmienia się co noc, choć nikt nie zapisuje rekordu, więc roll-up nie ma od czego się przeliczyć. Taka liczba potrzebuje przepływu harmonogramowanego albo raportu. - Filtr też ma limity: żadnego długiego obszaru tekstowego, listy wielokrotnego wyboru, pola Description, pól systemowych takich jak Last Activity, formuł międzyobiektowych ani pól lookup.
- Roll-upów nie ma na stronach edycji, więc reguła sprawdzania poprawności może z nich korzystać, ale nie może tam pokazać swojego błędu.
I nie odwracaj decyzji. Nie mów: „Potrzebujemy roll-upu, więc to musi być master-detail”. Mów: „Ten rekord podrzędny naprawdę należy do tego rodzica, własność i cykl życia pasują, a jedną z korzyści są natywne roll-upy”. Jeśli semantyka nie pasuje, rozwiąż obliczenie inaczej. Nie wykrzywiaj modelu danych, żeby dostać funkcję.
Jaki jest więc ten inny sposób? Budujesz roll-up sam: pole na rodzicu, które przechowuje wyliczoną wartość, i automatyzację, która utrzymuje je aktualne. Powiedzmy, że partner detaliczny jest lookupem z dostawy, tak jak powinien, a biznes chce mieć na partnerze liczbę otwartych dostaw (Open Deliveries). Dodaj do partnera pole liczbowe Open Deliveries. Potem przepływ wyzwalany rekordem (record-triggered flow) albo trigger Apex, gdy wolumen lub logika wymagają kodu, przelicza je przy każdej zmianie dostawy. Działa przez lookup, może filtrować po czymkolwiek i może używać dat i formuł, których natywny roll-up nie obsłuży.
Ale teraz to ty odpowiadasz za poprawność, i właśnie tu takie rozwiązania się sypią. Automatyzacja musi się uruchamiać przy każdej istotnej zmianie: nowym rekordzie podrzędnym, edytowanym, usuniętym, przywróconym i rekordzie podrzędnym przeniesionym do innego rodzica, co oznacza przeliczenie zarówno starego, jak i nowego rodzica. Musi obsłużyć ładowanie danych po 200 rekordów naraz bez przekraczania limitów. Przeliczaj od nowa, zamiast dodawać i odejmować, żeby jedno pominięte zdarzenie nie zostawiło błędnej liczby na zawsze. Zaplanuj sposób przeliczenia wszystkiego, na pierwsze ładowanie i na dzień, w którym wartości się rozjadą. I pamiętaj, że każdy zapis rekordu podrzędnego aktualizuje teraz rodzica, więc rodzic z tysiącami dzieci przywraca blokowanie, które zaraz zobaczymy. Natywny roll-up robi to wszystko za ciebie; własny to mały kawałek oprogramowania, którego jesteś właścicielem.
Trzy poziomy w głąb: piętrowanie relacji master-detail
Dział zatytułowany „Trzy poziomy w głąb: piętrowanie relacji master-detail ”Platforma ma kształt, a master-detail ma dwa jego wymiary. Pierwszy to głębokość.
Relacje master-detail możesz piętrować na trzy niestandardowe poziomy szczegółowe w głąb i na tym koniec (Considerations for Object Relationships (opens in a new tab), po angielsku). Na zajęciach rysuję to jako konto z zamówieniem (jeden), zamówienie z pozycjami (dwa) i pozycje z ich szczegółami (trzy), a potem próbuję dodać czwarty i Salesforce mi nie pozwala. W Steve Trucking mogłoby to wyglądać tak: dostawa (Delivery) jest rekordem nadrzędnym; jej pozycje dostawy (Delivery Items) to pierwszy poziom; zadania instalacyjne pozycji (Install Tasks) to drugi; a kroki zadania (Task Steps) każdego zadania to trzeci. Czwarty poziom, powiedzmy notatka do kroku (Step Note), musi być lookupem.
Ze stosem przychodzi kilka zasad:
- Obiekty standardowe nie mogą być po stronie szczegółowej obiektu niestandardowego. Obiekt niestandardowy może być rekordem szczegółowym konta; konto nie może być rekordem szczegółowym twojego obiektu.
- Obiekt może wystąpić tylko raz w wielopoziomowym stosie. Salesforce nie chce, żebyś zawracał do samego siebie: rekord podszczegółowy nie może być jednocześnie rekordem nadrzędnym własnego rekordu nadrzędnego.
- Rekord nadrzędny nie może bezpośrednio podsumować najniższego poziomu. Jeśli dostawa chce liczby kroków zadań, zadanie instalacyjne podsumowuje swoje kroki, pozycja dostawy podsumowuje te podsumowania, a dostawa podsumowuje pozycje: poziom po poziomie.
- Własność i udostępnianie przychodzą z góry. Każdy poziom dziedziczy właściciela i dostęp rekordu nadrzędnego.
- Usunięcie rekordu nadrzędnego usuwa wszystko pod nim, a jego przywrócenie przywraca wszystko.
Trzy poziomy zwykle w zupełności wystarczą. Jeśli twój projekt wciąż chce czwartego, zapytaj, czy każdy poziom naprawdę należy do tego nad nim przez całe życie. I pamiętaj, że to ty wybierasz, które ogniwo przerywa łańcuch. Czwarty poziom nie musi być lookupem: może zadanie instalacyjne tak naprawdę nie należy do swojej pozycji dostawy, bo jest planowane i przydzielane osobno, więc to ogniwo staje się lookupem, a zadanie instalacyjne zaczyna nowy łańcuch z krokiem zadania i notatką do kroku pod sobą. Wybierz ogniwo, w którym rekord podrzędny naprawdę ma własne życie, i to z niego zrób lookup.
Teraz zadanie instalacyjne ma własnego właściciela i własne udostępnianie, dostawę można usunąć, nie zabierając ze sobą jej zadań instalacyjnych, a pod zadaniem instalacyjnym zmieszczą się jeszcze dwa poziomy. Taki jest kompromis: łańcuch jest krótszy, a życie zadania instalacyjnego należy do niego samego.
Dwóch rodziców wszerz: obiekt łączący Salesforce
Dział zatytułowany „Dwóch rodziców wszerz: obiekt łączący Salesforce ”Najpierw słowo o słowach, bo „obiekt łączący” znaczy dwie rzeczy i uczę obu.
W rozdziale 2 znaleźliśmy logiczny obiekt łączący: połączenie dwóch kluczowych pojęć, które staje się osobną rzeczą, z własnymi atrybutami. Pies zna wiele sztuczek, sztuczkę zna wiele psów, a sztuczka psa siedzi między nimi i przechowuje poziom umiejętności i datę. To logiczny obiekt łączący, w modelu logicznym, na długo zanim ktokolwiek zdecyduje o lookup czy master-detail.
Salesforce używa tego terminu węziej. Gdy Salesforce mówi „junction object”, ma na myśli obiekt niestandardowy z dwiema relacjami master-detail (Create a Many-to-Many Object Relationship (opens in a new tab), po angielsku). Będę go nazywał obiektem łączącym Salesforce (Salesforce Junction Object). Każdy obiekt łączący Salesforce jest logicznym obiektem łączącym, ale nie każdy logiczny obiekt łączący staje się obiektem łączącym Salesforce: zbuduj go z jedną relacją master-detail i jednym lookupem albo z dwoma lookupami, a nadal będzie logicznym obiektem łączącym, tylko nie w wydaniu Salesforce. (Salesforce sam nie jest tu idealnie konsekwentny: jego własna dokumentacja obiektów nazywa niektóre obiekty standardowe zbudowane na lookupach „junction objects”. Na egzaminie przyjmij wąską definicję).
Wiedza egzaminacyjna. Obiekt łączący Salesforce (Salesforce Junction Object) to obiekt niestandardowy z dwiema relacjami master-detail i to właśnie Salesforce ma na myśli, mówiąc „junction object”. Logiczny obiekt łączący to szersza idea modelowania: dowolny obiekt, który łączy dwa inne w relacji wiele-do-wielu i niesie własne atrybuty, niezależnie od tego, jak go zbudowano.
Drugi wymiar to szerokość. Czy rekord podrzędny może mieć dwóch rodziców master-detail? Tak. Trzech? Nie. Każdy obiekt niestandardowy może mieć najwyżej dwie relacje master-detail (Considerations for Object Relationships (opens in a new tab), po angielsku). Dwóch rodziców master-detail to sposób na zbudowanie obiektu łączącego Salesforce dla relacji wiele-do-wielu. Ekipa (Crew) i ciężarówka (Truck) spotykają się w przydziale ekipy (Crew Assignment), a jak ustaliliśmy w rozdziale 2, to nie hydraulika: ma datę, trasę, może status. Obiekt łączący to miejsce, w którym relacja staje się pojęciem biznesowym. Wskazówki Salesforce do jego budowy: nadaj mu nazwę, która mówi, czym jest, niech nazwa rekordu będzie autonumerem i zmień nazwę listy powiązanej każdego rekordu nadrzędnego na nazwę drugiego rodzica, tak żeby strona ekipy pokazywała „Ciężarówki”, a strona ciężarówki „Ekipy” (Create a Many-to-Many Object Relationship (opens in a new tab), po angielsku).
A teraz zawiłość. Jeden z dwóch rodziców jest główny (primary) i jest nim ten, którego pole master-detail utworzono jako pierwsze. Nic wizualnie nie wskazuje, który to jest, więc to klasyczne pytanie egzaminacyjne i klasyczna niespodzianka.
O czym decyduje rodzic główny? O trzech rzeczach (Create a Many-to-Many Object Relationship (opens in a new tab), po angielsku):
- Wygląd. Strony obiektu łączącego używają koloru i ikony głównego rekordu nadrzędnego.
- Właściciel. Rekordy obiektu łączącego dziedziczą właściciela głównego rekordu nadrzędnego. Nigdy go nie widzisz, bo rekord szczegółowy nie ma pola Właściciel; ma to znaczenie tylko wtedy, gdy później usuniesz obie relacje master-detail.
- Dział (Division), jeśli twój org używa działów, w ten sam sposób.
A drugi jest drugorzędny (secondary). Co to znaczy?
- Jest następny w kolejce do roli głównego. Usuń główne pole master-detail albo przekonwertuj je na lookup, a drugorzędny stanie się główny.
- Wyznacza zakres raportów. Salesforce daje ci dwa typy raportów: „Primary master with junction object and secondary master” oraz „Secondary master with junction object and primary master”. Rekord nadrzędny wymieniony jako pierwszy decyduje, które rekordy raport może pokazać.
- Liczy się tak samo przy dostępie. Ujmuję to tak: własność od głównego, dostęp od obu, a wygrywa najbardziej restrykcyjny. Obiekt łączący, jak każdy obiekt szczegółowy, nie ma własnej tabeli udostępniania. Salesforce sprawdza dostęp użytkownika do obu rekordów nadrzędnych, przez Sharing Setting w każdym polu master-detail. Jeśli oba są ustawione na Read/Write, użytkownik potrzebuje Read/Write do ekipy i do ciężarówki, żeby edytować przydział ekipy (Considerations for Object Relationships (opens in a new tab), po angielsku).
- Usuwa tak samo. Usuń którykolwiek rekord nadrzędny, ekipę albo ciężarówkę, a jego rekordy obiektu łączącego trafią do Kosza. Usuń oba, a znikną na dobre.
Kilka kolejnych zasad: oba rekordy nadrzędne mogą mieć podsumowania zbiorcze z obiektu łączącego, a formuły i reguły sprawdzania poprawności obiektu łączącego mogą sięgać do pól obu. Ale obiekt łączący nie może być rekordem nadrzędnym niczego innego, więc nie może stać w środku stosu, a dwa rekordy nadrzędne nie mogą być tym samym obiektem; relacja wiele-do-wielu z obiektu do niego samego wymaga innego projektu. A jeśli rodzic ma ponad 200 rekordów obiektu łączącego, a obiekt łączący podsumowuje się do drugiego rodzica, Salesforce nie pozwoli usunąć tego rodzica, dopóki nie usuniesz wystarczająco wielu z nich.
Który rodzic powinien więc być główny? Utwórz najpierw ten, który jest właścicielem znaczenia. W przydziale ekipy pracę wykonuje ekipa, więc utworzyłbym najpierw ekipę. A potem to zapisz, bo nic na ekranie nie powie tego następnej osobie.
Po tym wszystkim przyznam, że nie kończę z wieloma obiektami łączącymi Salesforce. Zwykle obiekt ma jednego rodzica master-detail i są to dane tego samego rodzaju: dane klienta pod danymi klienta, transakcyjne pod transakcyjnymi (pamiętasz rodzaje danych z rozdziału 2: klienta, transakcyjne, referencyjne). Gdy jego drugi rodzic jest innego rodzaju, zwykle obiektem referencyjnym, ta relacja jest lookupem. Pozycja dostawy należy do swojej dostawy: master-detail, obie transakcyjne. Na produkt, który przewozi, wskazuje lookupem, bo produkt to dane referencyjne z własnym życiem i nikt nie chce, żeby usunięcie produktu zabrało ze sobą lata historii dostaw. Pozycja dostawy nadal jest logicznym obiektem łączącym między dostawą a produktami na niej; po prostu nie jest obiektem łączącym Salesforce.
Relacje do samego siebie: gdy linia wraca
Dział zatytułowany „Relacje do samego siebie: gdy linia wraca ”Obiekt może wiązać się sam ze sobą: konto nadrzędne, przełożony, centrum dystrybucyjne podlegające regionalnemu węzłowi. Salesforce ma wbudowane dwie takie relacje, które spotkasz niemal w każdym orgu: konto do konta, czyli pole konto nadrzędne (Parent Account), które buduje hierarchię kont, oraz zgłoszenie do zgłoszenia, czyli zgłoszenie nadrzędne (Parent Case) z modułu 2, które grupuje powiązane zgłoszenia. Relacja do samego siebie musi być lookupem, a rekord nie może wskazywać na siebie, choć dwa rekordy mogą wskazywać na siebie nawzajem (Considerations for Object Relationships (opens in a new tab), po angielsku). Na obiekcie User to osobny, specjalny typ, relacja hierarchiczna, używana na przykład do przełożonego użytkownika. Mechanika jest prosta; liczy się nazewnictwo. Lookup z centrum dystrybucyjnego do centrum dystrybucyjnego o nazwie Distribution_Center__c nikomu nie pomaga. Nadrzędne? Zapasowe? Na nadmiar? Nazwij relację według roli, a nie według obiektu, na który wskazuje.
Hierarchiczna: własna relacja obiektu User
Dział zatytułowany „Hierarchiczna: własna relacja obiektu User ”Ta jest mała i to dokładnie ten rodzaj mało znanego, jedynego w swoim rodzaju faktu, po który spodziewałbym się, że sięgnie egzamin. Relacja hierarchiczna to specjalny lookup, który istnieje tylko na obiekcie User. Łączy jednego użytkownika z innym, a Salesforce nie pozwala, żeby łańcuch zawrócił: użytkownik nie może wskazywać na siebie, ani bezpośrednio, ani pośrednio (Object Relationships Overview (opens in a new tab), po angielsku). Jeśli przełożonym Marii jest Dev, przełożoną Deva nie może być Maria ani nikt, kto podlega Marii.
Na tym polega różnica wobec relacji do samego siebie opisanych wyżej. Na koncie albo obiekcie niestandardowym dwa rekordy mogą wskazywać na siebie nawzajem. Na obiekcie User hierarchia musi pozostać hierarchią. I to jedyny sposób powiązania użytkownika z użytkownikiem: zwykły lookup z User do User nie jest dostępny.
Jedną już masz. Standardowe pole Manager na obiekcie User to relacja hierarchiczna i mogą z niej korzystać zatwierdzenia: wyślij ten wniosek do przełożonego zgłaszającego. Możesz też tworzyć własne, na przykład Escalation Contact albo Backup Approver, a zatwierdzenie może być kierowane wzdłuż nich w ten sam sposób (ApprovalProcess, Metadata API (opens in a new tab), po angielsku). Nie myl jej z hierarchią ról, która steruje dostępem do rekordów. Pole hierarchiczne to tylko relacja między użytkownikami; nie udostępnia ani jednego rekordu.
Wiedza egzaminacyjna. Relacja hierarchiczna istnieje tylko na obiekcie User, jak standardowe pole Manager, a użytkownik nie może wskazywać na siebie, ani bezpośrednio, ani pośrednio. To nie jest hierarchia ról.
Relacje też mają limity
Dział zatytułowany „Relacje też mają limity ”Każdy obiekt może mieć co najwyżej dwie relacje master-detail. Pola lookup i master-detail razem liczą się jako pola relacji: domyślnie 40 na obiekt, maksymalnie 50 na wniosek. Pola podsumowania zbiorczego: domyślnie 25 na obiekt, maksymalnie 40 (Increase the Maximum Relationships Allowed per Object (opens in a new tab); Increase the Maximum Limit of Roll-Up Summary Fields (opens in a new tab), po angielsku). Salesforce dodaje, że podniesienie któregokolwiek limitu może wpłynąć na wydajność.
Nie musisz projektować pod te liczby; musisz zauważyć, kiedy się do nich zbliżasz. Obiekt, na którym wisi relacja za relacją, coś ci mówi. Może naprawdę jest tak centralny. A może model jest zły. (I obowiązuje zasada zapasu z rozdziału 18: trzymaj się wyraźnie poniżej limitu, mierząc w trzecim roku).
Pytanie o 10 000 rekordów podrzędnych
Dział zatytułowany „Pytanie o 10 000 rekordów podrzędnych ”Jest też rodzic ze zbyt wieloma dziećmi. Własne zalecenie Salesforce mówi, żeby nie przekraczać około 10 000 rekordów podrzędnych na jednego rodzica w relacji master-detail (Considerations for Object Relationships (opens in a new tab), po angielsku), a przewodnik po dostępie do rekordów w dużej skali mówi to samo o relacjach rodzic-dziecko ogólnie (Parent-Child Data Skew (opens in a new tab), po angielsku). Rekord 10 001 nie psuje orgu. Ale powyżej tego progu zapis rekordu podrzędnego może blokować rodzica, a zmiany udostępniania na rodzicu rozchodzą się na każdy rekord podrzędny.
Kiedy więc widzę jednego rodzica i ogromną liczbę dzieci, pytam: dlaczego wszystkie są pod tym samym rodzicem, kto jest ich właścicielem, jak się je odpytuje i jaka automatyzacja dotyka rodzica? Wszystkie dostawy pod jednym kontem „Steve Trucking” przekroczyłyby 10 000 w kilka dni. Niewinna relacja jeden-do-wielu staje się problemem nierównomiernego rozkładu. Następny moduł zapowiada ten temat, a część 2 wchodzi w niego głęboko.
Nie projektuj linii pod funkcję
Dział zatytułowany „Nie projektuj linii pod funkcję ”Oto nawyk, którego chcę z tego modułu. Nie zaczynaj od „potrzebuję roll-upu”, „potrzebuję, żeby było wymagane”, „chcę dziedziczonego udostępniania”. To wskazówki implementacyjne. Zacznij od biznesu: czy rekord podrzędny ma własne życie, kto jest jego właścicielem, czy może istnieć sam, czy może się przenosić, co się dzieje, gdy rodzic znika, czy relacja niesie dane i jak duża może być każda strona? Potem wybierz relację, która implementuje odpowiedzi.
Poza egzaminem: co zmienia AI. AI potrafi zaproponować relacje w kilka sekund. Nie powie ci, czy biznes kiedykolwiek usunie rodzica. Szybsze rysowanie diagramów nie sprawia, że błędną relację taniej odwrócić, gdy zależą od niej miliony rekordów i dziesiątki automatyzacji.
Co tu decyduje architekt
Dział zatytułowany „Co tu decyduje architekt ”- Czy rekord podrzędny ma własny cykl życia, czy naprawdę należy do rodzica, i czy własność i dostęp mają być własne, czy dziedziczone.
- Czy rekord podrzędny może istnieć bez rodzica, przenosić się między rodzicami albo przetrwać usunięcie rodzica.
- Co robi każdy lookup, gdy jego rodzic zostaje usunięty: czyści, blokuje czy usuwa kaskadowo.
- Czy relacja wiele-do-wielu to hydraulika, czy pojęcie biznesowe, czy logiczny obiekt łączący staje się obiektem łączącym Salesforce, który rodzic jest główny i co obaj rodzice oznaczają dla dostępu.
- Czy model pasuje do kształtu platformy: trzy niestandardowe poziomy szczegółowe w głąb, dwóch rodziców master-detail wszerz, limity relacji i roll-upów.
- Czy oczekiwana liczba i rozkład rekordów podrzędnych tworzą ryzyko nierównomiernego rozkładu, które powinno zmienić projekt.
Relacja to zestaw obietnic o tym, jak dwa elementy danych zachowują się razem. Składaj je świadomie.
Do zgłębienia
Dział zatytułowany „Do zgłębienia ”- Pomoc Salesforce, Considerations for Object Relationships (opens in a new tab) (po angielsku), sprawdzono 2026-10-13.
- Pomoc Salesforce, Object Relationships Overview (opens in a new tab) i Create a Many-to-Many Object Relationship (opens in a new tab) (po angielsku), sprawdzono 2026-10-13.
- Pomoc Salesforce, Roll-Up Summary Field (opens in a new tab) (po angielsku), sprawdzono 2026-10-13.
- Salesforce Developers, Metadata API, ApprovalProcess (opens in a new tab) (po angielsku), sprawdzono 2026-10-13.
- Pomoc Salesforce, Lookup Filters (opens in a new tab) (po angielsku), sprawdzono 2026-10-13.
- Pomoc Salesforce, Increase the Maximum Relationships Allowed per Object (opens in a new tab) i Increase the Maximum Limit of Roll-Up Summary Fields (opens in a new tab) (po angielsku), sprawdzono 2026-10-02.
- Salesforce Developers, Designing Record Access for Enterprise Scale, Parent-Child Data Skew (opens in a new tab) (po angielsku), sprawdzono 2026-10-02.
