WPF + MVVM, Przechowywanie obiektów z bazy danych

0

Cześć,
Stworzyłem mały programik w ramach nauki i zastanawiam się jak go udoskonalić. Chodzi o połączenie z bazą danych i przechowywanie danych.
Program zawiera kilka widoków, w każdym z nich wykorzystuje pewną listę obiektów, które trzymam w bazie danych (lub jej część, lub dodatkowo przetwarzam te dane i dopiero wykorzystuje), wszystko z bindowanie, INotifyPropertyChanged itd. Teraz mam to zrobione tak, że w trakcie uruchomienia programu zaczytuję listę obiektów z bazy danych i przechowuję je w pamięci, w singletonie (to jest pierwszy niepewny punkt), tak abym mógł się dostać do danych bez problemu z każdego punktu programu. Nie wiem też czy dobrze jest zaczytywać wszystko na początku i operować na danych z pamięć czy za każdym razem jak chce wyświetlić listę lub jej część to mam ponownie wysyłać zapytanie do bazy danych.

3

Zalezy jak duża jest Twoja baza danych. Ale chyba lepiej za każdym razem wysyłać zapytanie, wtedy masz pewność, że dane które masz w pamięci nie są różne od tych w bazie

3

Teraz mam to zrobione tak, że w trakcie uruchomienia programu zaczytuję listę obiektów z bazy danych i przechowuję je w pamięci, w singletonie (to jest pierwszy niepewny punkt), tak abym mógł się dostać do danych bez problemu z każdego punktu programu. Nie wiem też czy dobrze jest zaczytywać wszystko na początku i operować na danych z pamięć czy za każdym razem jak chce wyświetlić listę lub jej część to mam ponownie wysyłać zapytanie do bazy danych.

A co jeśli w bazie będzie kilka milionów obiektów? Zaczytasz wszystkie? ;) Tak, wyślij jeszcze raz zapytanie oraz używaj stronicowania.

2

musisz do tego podejść zdroworozsądkowo - po pierwsze ile tych danych jest, po drugie jak często się one zmieniają i na ile ich "nieaktualność" ma wpływ na pracę a po trzecie jak często po nie sięgasz w programie. Jeśli są to jakieś słowniki, które generalnie uzupełnia się na raz i mają po kilkadziesiąt - kilkaset rekordów a sięgasz do nich co parę minut to możesz spokojnie raz je zaciągnąć i trzymać w pamięci. W końcu RAMu ci w komputerach dostatek :).

0

No ma to sens. A co w przypadku gdy muszę najpierw przetworzyć wszystkie rekordy? Np jakbym miał produkty i musiałbym zsumować cenę całkowitą i z jakiegoś okresu i jeszcze jakąś. To lepiej jest to robić po stronie bazy? Nawet jeżeli wiązałoby się to z JOIN-ami??

I jeszcze jedno:D Jeżeli w tabeli muszę przedstawić dane z kilku tabel, to dobrym pomysłem będzie stworzenie konkretnej klasy pod tą tabele (taki model pośredni, tak jak ViewModel w ASP MVC??)

1
vesper0990 napisał(a):

No ma to sens. A co w przypadku gdy muszę najpierw przetworzyć wszystkie rekordy? Np jakbym miał produkty i musiałbym zsumować cenę całkowitą i z jakiegoś okresu i jeszcze jakąś.

a co to jest cena całkowita? BTW to zależy od tego czy potrzebujesz tylko tą "cenę całkowitą" czy także poszczególne towary, które potem będziesz mocno wykorzystywał. Generalnie poza stałymi słownikami nie ma co niepotrzebnie pobierać danych "na później". W szczególności jeśli docelowo aplikacja ma mieć wielu userów to dane (jak np. sprzedaż za okres czy stan magazynowy) zmienia się na tyle szybko, że trzymanie tego w pamięci nie ma sensu

To lepiej jest to robić po stronie bazy? Nawet jeżeli wiązałoby się to z JOIN-ami??

Nie mam pojęcia co to wg Ciebie znaczy "po stronie bazy"

I jeszcze jedno:D Jeżeli w tabeli muszę przedstawić dane z kilku tabel, to dobrym pomysłem będzie stworzenie konkretnej klasy pod tą tabele (taki model pośredni, tak jak ViewModel w ASP MVC??)

To też zależy - jeśli ten "widok" będzie niezmienny (chodzi o kolumny, które chcesz pokazać) to możesz go opakować w dodatkową klasę

0
vesper0990 napisał(a):

No ma to sens. A co w przypadku gdy muszę najpierw przetworzyć wszystkie rekordy? Np jakbym miał produkty i musiałbym zsumować cenę całkowitą i z jakiegoś okresu i jeszcze jakąś. To lepiej jest to robić po stronie bazy? Nawet jeżeli wiązałoby się to z JOIN-ami??

I jeszcze jedno:D Jeżeli w tabeli muszę przedstawić dane z kilku tabel, to dobrym pomysłem będzie stworzenie konkretnej klasy pod tą tabele (taki model pośredni, tak jak ViewModel w ASP MVC??)

Wtedy lepiej zrobić zapytanie pobierajace wszystkie komórki danej kolumny z danej tabeli. Ograniczasz zużycie danych

0
vesper0990 napisał(a):

No ma to sens. A co w przypadku gdy muszę najpierw przetworzyć wszystkie rekordy? Np jakbym miał produkty i musiałbym zsumować cenę całkowitą i z jakiegoś okresu i jeszcze jakąś. To lepiej jest to robić po stronie bazy? Nawet jeżeli wiązałoby się to z JOIN-ami??

A w czym joiny w aplikacji lepsze od tych w bazie?
Możesz to zrobić po stronie zarówno aplikacji (wysyłając odpowiedni SQL, albo definiując odpowiednią agregację w ORMie) a także po stronie bazy.
Wszystko zależy od tego, do czego to tak naprawdę potrzebujesz, czy to ma być jakiś np. raport, czy chcesz mieć te dane utrwalone, i jak często będziesz z nich korzystał.

I jeszcze jedno:D Jeżeli w tabeli muszę przedstawić dane z kilku tabel, to dobrym pomysłem będzie stworzenie konkretnej klasy pod tą tabele (taki model pośredni, tak jak ViewModel w ASP MVC??)

Używasz słowa "tabela" w jednym zdaniu w prawdopodobnie dwóch znaczeniach, co utrudnia zrozumienie pytania.

0

Chodzi o takie dane, które zmieniają się dość często. Zrobimy coś w programie przez co doszło parę rekordów i trzeba odświeżyć jakieś wykresy np. No tak nie zauważyłem, chodziło mi żeby do jednego DataGrid wstawić dane które są zawarte w kilku tabelach w bazie danych.

0

Witam,

Może powiedz ile tych danych będzie i w jakiej bazie chcesz je przechowywać? Np SQL Server pozwala na przesyłanie notyfikacji (https://www.nuget.org/packages/SqlTableDependency/). Poza tym zawsze możesz wstawić jakąś warstwę pośrednią która będzie gadała z twoim programem zwracając Ci gotowe obiekty i kolekcje a dodatkowo informowała o tym że coś się zmieniło.

Pozdrawiam,

mr-owl

0
vesper0990 napisał(a):

Chodzi o takie dane, które zmieniają się dość często. Zrobimy coś w programie przez co doszło parę rekordów i trzeba odświeżyć jakieś wykresy np.

A te wykresy mają się zmieniać w czasie rzeczywistym, czy po prostu po wejściu na odpowiedni ekran, czy może użytkownik ma mieć dostępny jakiś przycisk "odśwież"?

No tak nie zauważyłem, chodziło mi żeby do jednego DataGrid wstawić dane które są zawarte w kilku tabelach w bazie danych.

No to zrób sobie viewodel do tego DataGrida. To zresztą nawet oczywiste, że do każdego ekranu aplikacji powinieneś mieć oddzielny ViewModel.

0

Aplikacja jest typu fiszki, gdzie użytkownik robi sobie swoje grupy słów do nauki, z serwerem online, żeby można było mieć te same słówka np na telefonie, albo innym komputerze. Ze stroną serwera nie ma problemów, wiem, że za każdym razem jak chce zobaczyć słowa na stronie to muszę odczytywać je z bazy. Ale bardziej mi chodzi o stronę desktopową albo na urządzeniu mobilnym. Rekordów może być dajmy na to 10tyś, ale każdy z rekordów może się dość często zmieniać (słowo zawiera w sobie informacje o szufladzie w której teraz się znajduje), ale tylko w określonych miejscach (tylko jak użytkownik odbędzie lekcje).

Dokładnie nie chodzi mi o mój przykład strikte (dlatego nie przedstawiałem go na początku). Chodziło mi raczej o regułę - o ile taka jest - czy lepiej jest zawsze operować na bazie, bo mamy wtedy pewność, że to są rzeczy z "pierwszej ręki" i mamy je tylko w jednym miejscu, czy raczej zaczytać dane do pamięci i operować na niej, ale martwić się o poprawny update bazy po tym jak użytkownik zmieni coś. Dodatkowym założeniem jest to, że użytkownik wymuszałby operację na danych dość często - w moim przypadku to jest z przejścia z jednego okna na drugie np: informację o wynikach na oknie powitania, okno budowania grup, okno ze słowami, okno nauki itp. Gdybym wybrał zawsze odczytywanie z bazy danych, czy to nie pogorszyłoby wydajności programu w znaczący sposób. Chodzi mi o ogólną dyskusję, niekoniecznie o konkretny przypadek

0

No, ale nie da się ogólnie dyskutować, bo nie ma ogólnych zasad (poza takimi jak "zrób to dobrze" ;)).

Każdy użytkownik ma swoją listę słów? Czy wszystkie słowa są używane podczas jednej sesji pracy z programem?

1

No to zrób sobie viewodel do tego DataGrida. To zresztą nawet oczywiste, że do każdego ekranu aplikacji powinieneś mieć oddzielny ViewModel.

Powiem więcej: nawet do zbioru kontrolek reprezentujących jeden kontekst zamiast do całego ekranu, czyli per UserConrol. No chyba, że ilość kontrolek w oknie jest nieduża, bo inaczej XAML potrafi rozrosnąć się do niebotycznych rozmiarów.

0

Każdy użytkownik ma swoją listę słów, ale może być wielu użytkowników (oczywiście rozpatrujemy tylko jednego użytkownika i nie zaczytujemy słów innych)
W zależności czy użytkownik zrobi pewne akcje, bądź nie może się zdarzyć, że zaczytane będą wszystkie słowa, np jeżeli użytkownik wejdzie tylko w jedną lekcje będzie miał "interakcję" tylko z tymi słowami, ale jednak chcę aby na ekranie powitalnym znajdowały się takie informacje jak ilość słów które ma dany użytkownik z podziałem na to w której są szufladzie, ile ma grup, ile odbył lekcji, ile te lekcje trwały, ile trwały danego dnia, może więcej w przyszłości... Gdybym zaczytał to do pamięci to nie "rzeźbił" po bazie za każdym razem jak zostanie wyświetlone menu główne.

-przy okazji jeszcze mam pytanie czy select blokuje bazę danych? Czy mogę wykonywać wiele selectów w różnych wątkach niezależnie od siebie na tej samej tabeli?

0
vesper0990 napisał(a):

W zależności czy użytkownik zrobi pewne akcje, bądź nie może się zdarzyć, że zaczytane będą wszystkie słowa, np jeżeli użytkownik wejdzie tylko w jedną lekcje będzie miał "interakcję" tylko z tymi słowami

To ja bym odczytywał słowa dla danej lekcji do pamięci, akcje użytkownika wykonywał w pamięci, a np. przy wyjściu z lekcji czy zamknięciu aplikacji zapisał zmiany do bazy.

ale jednak chcę aby na ekranie powitalnym znajdowały się takie informacje jak ilość słów które ma dany użytkownik z podziałem na to w której są szufladzie, ile ma grup, ile odbył lekcji, ile te lekcje trwały, ile trwały danego dnia, może więcej w przyszłości... Gdybym zaczytał to do pamięci to nie "rzeźbił" po bazie za każdym razem jak zostanie wyświetlone menu główne.

To należałoby utworzyć jakąś tabelę na statystyki użytkownika, i też odczytywać ją przy otwarciu programu, a zapisywać po zakończeniu lekcji.

-przy okazji jeszcze mam pytanie czy select blokuje bazę danych? Czy mogę wykonywać wiele selectów w różnych wątkach niezależnie od siebie na tej samej tabeli?

To zależy od poziomu izolacji transakcji... no i ogólnie ma średni sens, nie masz tych danych aż tak dużo, żeby to mogło dać jakiś zysk.

0

Mam trzy tabele (tak w skrócie):
Group - grupy użytkownika
Word - słowa z przypisaną szufladą
Result - wyniki z lekcji - kiedy, jaki rodzaj lekcji, ile dobrych/złych odpowiedzi, jak długo trwała itp.
Aby wyświetlić wyniki muszę odczytywać dane z nich wszystkich.
Tobie chodzi o to żebym dla użytkownika stworzył tabelę gdzie w określonych kolumnach będą te dane, które chce wyświetlić na ekranie początkowym? Nie wiem czy to dobry pomysł, chociażby dlatego, że jeżeli będę chciał się dowiedzieć o wynikach z konkretnego dnia to i tak będę musiał operować na danych z tabeli Result.

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