Wysyłanie danych do chmury - RestAPI, czy coś innego?

0

Cześć, zastanawiam się nad takim zadaniem.

Jest aplikacja, która pozwala na trzymanie danych lokalnie (Sqlite), ale też w chmurze (MSSQL).
Zaszła potrzeba, żeby zająć się teraz chmurą.
I teraz tak. Mam ileś tam klas modeli biznesowych, które mają między sobą różne zależności, np. jedna klasa ma w sobie listę innych klas:

W uproszczeniu to wygląda tak:

public class ParentModel: DbItem
{
  public IList<ChildModel> SubItems {get; set;}
}

public class ChildModel: DbItem
{
  public IList<AnotherChildModel> SubItems {get; set;}
}

public class AnotherChildModel: DbItem
{
  public AnotherClass ConnectedItem {get; set;}
  public IList<DetailItem> SubItems {get; set;}
}

I teraz jak najlepiej ogarnąć wysyłanie danych na serwer?
Użytkownik nie zmieni całego dokumentu, tylko poszczególne itemy. Dlatego też muszę wysłać na serwer tylko te zmienione itemy.
Zrobiłem sobie klasy DTO - odpowiedniki dla każdego elementu modelu tyle, że bez list, np:

public class AnotherChildDto
{
    public Guid ConnectedItemId { get; set; }
}

public class DetailItemDto
{
  public Guid ParentId {get; set;}
}

I teraz pytanie, czy to faktycznie dobre rozwiązanie, żeby robić jsona z takiej struktury DTOsów i wysyłać to do RestApi? Po stronie serwera odtwarzać z tego modele i pakować je do bazy danych? Czy może jest jakieś inne/lepsze rozwiązanie na coś takiego?

Głównym moim tutaj czerwonym światłem jest potrzeba sprawdzania typu każdego elementu.

Mam takie Dto, które będę pchał:

public class DocumentSaveDto
{
    public List<ParentModelDto> ParentModels {get; set;}
    public List<ChildModelDto> ChildModels {get; set;}
   //itd.
}

I teraz muszę zrobić coś takiego:

DocumentSaveDto dto = new DocumentSaveDto();

foreach(var item in document.ModifiedItems)
{
    //pseudokod:
   switch(item.GetType())
   {
        case ParentModel: 
            dto.ParentModels.Add(new ParentModelDto(item));
            break;

        case ChildModel:
           dto.ChildModels.Add(new ChildModelDto(item));
           break;
       //itd
   }
}
0

Bardzo nie podoba mi się to rozwiązanie. Wymyśliłem coś innego, ale nie wiem jak tu jest z bezpieczeństwem. Pewnie licho, ale proszę o feedback. Wszystko działa na zasadzie bezpośredniego dostępu do bazy danych z lekkim użyciem rest (wszystko na SSL):

  • użytkownik loguje się do aplikacji klienckiej
  • aplikacja wysyła restem dane do serwera
  • serwer sprawdza usera, jeśli ok, wysyła mu token
  • user chce pobrać listę dokumentów, klika guzik "Pobierz"
  • aplikacja wysyła zapytanie restem, czy można pobrać dokumenty dla usera od ID = x
  • serwer zwraca odpowiedź, że można i odsyła zakodowany connection string do bazy
  • aplikacja kliencka odkodowuje sobie connectionstring i łączy się bezpośrednio z bazą, pobiera dokumenty i kończy połączenie
    ...
  • user chce zapisać dokument po modyfikacjach, klika ZAPISZ
  • aplikacja pyta się restem serwera, czy user może to zrobić
  • serwer odpowiada, że może i odsyła zakodowany connectionstring
  • apka odkodowuje go, łączy się z bazą danych i robi odpowiednie zmiany.

Czyli całość wygląda mniej więcej tak:
Jeśli operacja jest prosta (np. usunięcie dokumentu o podanym id) - wszystko może lecieć restem.
Jeśli operacja jest skomplikowana (np. modyfikacja wielu rekordów w wielu tabelach) - aplikacja kliencka pyta się restem, czy może to zrobić. Jeśli serwer się zgodzi, odsyła zakodowany connectionstring. Aplikacja sobie go odkodowuje (kluczem może być username + password), łączy się z bazą i ORM wykonuje potrzebne operacje.

Dzięki temu unikamy przesyłania dużych paczek danych jsonem, czy XMLem i możemy pozbyć się sporej ilości klas DTO.

Co Wy myślicie o takim rozwiązaniu?

0

Licho. Z pewnością nie będzie problemów żeby sobie z pamieci wyciągnąć tego connection stringa i robić co się chcę z twoją bazą. Kolega wspomniał o thrifcie, jest też avro i wiele innych narzędzi, dzięki którym możesz zmniejszyć (jakims kosztem, np posiadania schemy obietu) dane, które będa leciały na serwer. Generalnie nie podałeś konkretów co chcesz robić, ale pierwsze dwa pytania jakie mi sie nasuwają to czy zmierzyłeś ile danych bys faktycznie wysyłał i czy to jest dużo i jest to problem, że trzeba go rozwiązać, czy po prostu 'wydaje się dużo'. Druga sprawa jest taka, że jeżeli zmieniasz małą ilość rzeczy to możesz mieć API, które np. zmieni tylko jakiś atrybut danego obiektu i wysyłasz obiekt o wdzięcznej nazwie UserNameRequest zamiast wysyłać całego Usera, tak samo możesz wysłać tylko childy czy cokolwiek co bedzie się grupowało w jakąś logiczną akcje domenową. To oczywiście odpada, jeżeli użytkownik dokonuje faktycznie zmian w całym dużym formularzu, zamiast edycji np kilku pól, ale wtedy może dałoby radę zrobić jakiegoś krokowca i podzielić formularz na kilka mniejszych

0

To jest tak, że użytkownik pracuje na dokumencie i w pewnym momencie po prostu zapisuje zmiany. Więc wtedy lecą dane ze wszystkich zmienionych obiektów. Danych bardziej 'wydaje się dużo' niż ich jest. Jednak dokument może składać się np. z 10 arkuszy, które mają w sobie jeszcze po 12 innych złożonych obiektów. A użytkownik tak naprawdę robi zmiany w jednym podobiekcie w jednym arkuszu. Dlatego nie chcę wysyłać całej struktury dokumentu, bo to trochę bez sensu. Muszę wysłać tylko zmienione elementy. Jest to nieco uciążliwe jeśli chodzi o oprogramowanie. Cały mechanizm zapisania danych lokalnie mam i to jest proste. Natomiast problemem jest wysłanie tego do chmury w odpowiedniej strukturze. Bo po drugiej stronie muszę jakoś odtworzyć ten model, żeby wysłać do ORMa (w tym scenariuszu ORM stanowi pewne utrudnienie). Chyba, że stworzę w jakiś sposób częściową strukturę modelu i wyślę ją - zserializuję po prostu model zamiast bawić się w DTO.

0
Juhas napisał(a):

Muszę wysłać tylko zmienione elementy.

Ale co masz na myśli dokładnie? Zmienione elementy to obiekty czy proste wartości? Bo może po prostu łatwiej wysłać listę zmienionych wartości i ścieżek do nich?

Chyba, że stworzę w jakiś sposób częściową strukturę modelu i wyślę ją - zserializuję po prostu model zamiast bawić się w DTO.

No ja chyba też bym szedł w tym kierunku.

Zresztą, ja nie bardzo widzę miejsce dla RestAPI tutaj. Co jest właściwie zasobem, cała baza? :P

0

Poniekąd tak...
Tzn. mam np. taką strukturę:

  • Document, który zawiera klasy Parent
  • Parent zawiera klasy Child
  • Child zawiera klasy SecondChild itd.

Każda taka klasa ma swoją tabelę oczywiście.

I czasem będzie zmieniony tak naprawdę jeden obiekt (np. jedna wartość prosta w jednym obiekcie), a czasem kilka z nich.

0

Inaczej - jeśli w całym grafie jest powiedzmy tysiąc prostych wartości, a Ty chcesz zmienic 10, to wolałbym raczej wysłać listę zmian niż całe obiekty. Ale to też zależy od częstotliwości tych zmian, jeśli są rzadko, to moze jednak prościej całe obiekty - ale to może być zserializowany model, serio nie widzę zalet używania jakichś DTO tutaj.

1 użytkowników online, w tym zalogowanych: 0, gości: 1