Z mojego doświadczenia wynika, najczystsze (ale nie najłatwiejsze) rozwiązanie okazało przychodzi w 5 części:
- mającą autorytatywny model danych i tylny koniec, który jest zawsze na bieżąco : DAL/Database/Services.
- Posiadanie danych specyficznych dla wersji, które są zrozumiałe dla systemu: wiele modeli danych.
- Zapewnienie, że zmiany pomiędzy wersją są identyfikowane i śledzone prawidłowo i że zmiany są odwracalne. Reguły muszą być jawnie zdefiniowane, aby sobie z tym poradzić (co może być trudniejsze): Konwertery.
- Making klient wyraźnie powiedzieć, która wersja używają: Query Strings/nagłówków.
- Mając autorytatywny logiki biznesowej, która jest zawsze aktualne, ale wie, jak poruszać się pomiędzy inną wersję danych - kompatybilne wstecznie: Sterowniki.
Dane modelu mamy jest Dostawca np.
(1) Back End (tj. DAL/baza danych) znajduje się na poziomie V5. Logika biznesowa (tj. Usługi) jest również na V5.
(2) Jednak musimy służyć klienta dostawca V1, V2, V3, V4 i aktualne klienta na V5 wszystkich w tym samym czasie. Zróbmy V1 do V5 naszego modelu danych: SupplierV1, SupplierV2 ... (można używać nazw, lub innych sposobów, aby je różnicują)
(3) trzeba zdefiniować konwertery i zarządzać nimi. Muszą one obsługiwać zarówno kompatybilność w przód, jak i w tył między wersjami modeli danych. Można to zrobić za pomocą wzoru strategii, lambdas, menedżera z konwerterami DI itp.Będziesz musiał obsłużyć: V1-> V2-> V3-> V4-> V5, ale także V5-> V4-> V3-> V2-> V1.
Zasady dotyczące przetworników są najtrudniejsze. Czasami jest to łatwe - Wartości domyślne dla nowych pól. Innym razem musisz uruchomić jakąś logikę biznesową. Kiedyś musisz konwertować/scalać istniejące dane; musisz się upewnić, że jest odwracalny! Na przykład, jeśli wartości są w mieszanym przypadku w V1 i konwertujesz je na wielkie litery w V2 ... nie będziesz w stanie przywrócić go do wersji V1, ponieważ nie masz pojęcia, które znaki były wielkie i małe. Możesz obsłużyć to na dwa sposoby:
- Zachowaj go w dużych literach dla V1. Wszakże wymaga tego tylko V2, V1 prawdopodobnie działa ze wszystkimi dużymi przypadkami (oczywiście nie działałoby na klucze).
- Zachowaj starą wartość w polu w V2. Na przykład, jeśli zdecydujesz się na duże litery stanu pola, możesz zachować wartość oryginalną, która jest mieszana i skopiować ją do stanu po powrocie do wersji V1.
Jak widać, trzeba myśleć o tych trudnych i często nietrywialnych.
(4) Następnie w kontrolerach, trzeba wiedzieć, która wersja klient współpracuje z zrobić konwersję i wyjść regulatora, gdy są potrzebne. W tym celu można użyć ciągi zapytań, nagłówki (X-API-Version lub Zebrane na przykład, ale uważaj niektóre host/proxy paski niektóre z nich), parametr pisać itp
(5) W końcu, kiedy kontroler odbiera model danych, musisz sprawdzić, którą wersję wysłał klient (powiedzmy V2) i zaktualizować go do najnowszej wersji dla zaplecza (V5). Następnie użyj go poprawnie, a następnie, jeśli chcesz wysłać dane z powrotem, musisz obniżyć go do wersji klienta (V2). Aby to zrobić, można zrobić zwyczaj wiązania, działania niestandardowe żądanie, niestandardowe wyniki akcji, itp na przykład (proszę zautomatyzowania tego):
public IHttpActionResult DoSomethingWithSupplier(JToken supplier) // Receiving Json Supplier
{
// TODO: Get the client version type, for example in the X-API-Version header/query strings
// (beware, some proxy/hosts strips some headers)
// Type clientType = ...
var clientSupplier = JsonConvert.DeserializeObject(supplier.ToString(), clientType);
// You should probably detect latest version automatically (instead of typeof)
var latestSupplier = VersionManager.Upgrade(clientSupplier, clientType, typeof(SupplierV5));
outputSupplier = DoSomething(latestSupplier);
// You should probably detect latest version automatically (instead of typeof)
var clientOutputSupplier = VersionManager.Downgrade(outputSupplier, typeof(SupplierV5), clientType);
return Ok(clientOutputSupplier);
}
To bardzo surowy sposób, aby pokazać wam ten pomysł. To jest coś, co zrobiliśmy w jednym z naszych systemów. Możesz mieć menedżerów, którzy wykrywają typy i wersje i sami zajmują się konwersją, możesz dynamicznie ładować zespół/konwertery za pomocą wtrysku zależności, możesz zautomatyzować większość konwersji w niestandardowych powiązaniach/żądaniach akcji i tak dalej.
Uwaga: Jest też część (6) może trzeba rozważyć. Aby faktycznie zaktualizować dane klienta w bazie danych do wersji V5, można to zrobić podczas migracji do wersji V5 (migracja wsadowa danych), LUB, zrób to w czasie wykonywania. Kiedy otrzymasz SupplierV1, ładujesz go z bazy danych (nadal dane V1), dokonaj aktualizacji do wersji V5 i zapisz zaktualizowane dane, wszystkie w konwerterze. Oznacza to, że masz teraz w locie migrację twojego backendu. Oczywiście nie jest to tak proste, jak się wydaje, ponieważ musisz obsługiwać obie wersje w tej samej bazie danych, ale może Ci się to udać w zależności od rodzaju wprowadzonych zmian lub danych.
https://github.com/Sebazzz/SDammann.WebApi.Versioning – adt
To świetne rozwiązanie dla kontrolerów wersji, ale jak już powiedziałem, nie szukam tego. – Levitikon
Jedyne, co mogłem wymyślić; byłoby stworzyć samowystarczalny model, który przechowuje te dane. Następnie użyj kontrolera, aby pobrać te informacje. Lub, aby mieć oddzielną tabelę bazy danych, w której można wykorzystać te odniesienia. Nie jestem pewien, czy to pomoże, dobre pytanie, nad czym się zastanowię. – Greg