MVVM + EF czy dobrze?

0

Witajcie,

jak co niektórzy wiedzą uczę się Entity Framework i chcę go dobrze zastosować wespół z MVVM.

Teraz chcę się zapytać czy moje podejście jest dobre?

Wołam @DibbyDum i innych mvvm'owców.

PS: Wiem, że EF jest jaki jest ale mimo wszystko chcę go poznać. Później równolegle sobie może nHibernate zrobię.

1

Odnośnie ViewModelu:

  • Usuń magic stringi z property change
  • Operacje wyszukiwania oraz dodawania przesuń do osobnej klasy. Natomiast w ViewModelu używaj słabej referencji do tej klasy (Interfejsu). Zapewni to tobie większą możliwość testowania.
  • Uwaga od mnie ja bym przeniósł definicje akcji do osobnych method. Ułatwi to potem np. wprowadzenie Controllera.
3

Słowem wstępu MVVM to wzorzec architektury dzielący ogólnikowo aplikacje na trzy warstwy odseparowane od siebie.

  1. View odpowiada za GUI, czyli za wygląd formatek za wszelakie wodotryski czy to napisane w XAML czy w c# code-behind bez różnicy.
  2. ViewModel tutaj leci logika aplikacji, głownie odpowiedzialna za pobierz dane z Model przekaż do View i z powrotem.
  3. Model tutaj powinna być logika biznesowa (domena), serwisy, repozytoria i inne szmery bajer które korzystają na przykład z bazy danych za pośrednictwem EF.

A więc wracając do twojego kodu:

  1. Wywalić z ViewModel ten "DbContext" i ubrać to w jakieś serwisy po stronie modelu.
  2. Model to nie mapowanie tabelki z bazy danych.
  3. "DbContext" jak "DbContext" jest okej nie ma co się nad nim zastanawiać.

View, ViewModel i Model to ogólniki pod nimi zawsze kryją się bardziej szczegółowe wzorce i implementacje.

P.S. nie przepracowałem ani pół sekundy jako WPF/MVVM developer więc równie dobrze mogę pieprzyć głupoty. :)

0

To dopiero początek przygody z MVVM, pamiętam jak kląłem kiedy coś mi nie działało, MVVM jest "magiczne" :D

0

Dzięki wszystkim za feedback. No ja juz próbuję mvvm używać dobre dwa latka :) Ciągle dowiaduję się czegoś nowego :)

0

@DibbyDum, @teo215 Czy chodziło o taki serwis?

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Library.Model;

namespace Library.Services {
    public interface ILibraryService {
        ICollection<Book> GetBooks();
        ICollection<Author> GetAuthors();
        ICollection<BooksView> GetBooksView();

        bool InsertBook(Book book);
        bool InsertAuthor(Author author);
        bool Associate(int bookId, int authorId);
    }

    public class LibraryService : ILibraryService {
        public ICollection<Book> GetBooks() {
            using (var db = new LibraryContext()) {
                return db.Books.ToList();
            }
        }

        public ICollection<Author> GetAuthors() {
            using (var db = new LibraryContext()) {
                return db.Authors.ToList();
            }
        }

        public ICollection<BooksView> GetBooksView() {
            using (var db = new LibraryContext()) {
                return db.BooksView.ToList();
            }
        }

        public bool InsertBook(Book book) {
            try {
                using (var db = new LibraryContext()) {
                    db.Books.Add(book);
                    return db.SaveChanges() > 0;
                }
            }
            catch (Exception) {
                return false;
            }
        }

        public bool InsertAuthor(Author author) {
            try {
                using (var db = new LibraryContext()) {
                    db.Authors.Add(author);
                    return db.SaveChanges() > 0;
                }
            }
            catch (Exception) {
                return false;
            }
        }

        public bool Associate(int bookId, int authorId) {
            try {
                using (var db = new LibraryContext()) {
                    var book = db.Books.Single(b => b.Id == bookId);
                    var author = db.Authors.Single(a => a.Id == authorId);

                    book.Authors.Add(author);
                    author.Books.Add(book);

                    return db.SaveChanges() > 0;
                }
            }
            catch (Exception ex) {
                System.Windows.MessageBox.Show(ex.ToString());
                return false;
            }
        }
    }
}

Generalnie baza jest prosta. Taka tam... żeby ogarnąć działanie ORM:

61883b86f2.png

Klasy Book i Author to fizyczne tabele w bazie danych. Klasa BookView to klasa, która bierze dane z widoku zrobionego w bazie.
Czy chodziło o takie (albo podobne) podejście? :)

PS: Nie zwracajcie uwagi na ogolny Exception i to, że jest tam tylko return false. Chodzi generalnie o ideę serwisu. W viewmodelu będzie luźna referencja w postaci interfejsu.

1

Koncepcja jest ogólnie słuszna tylko zamiast ObservableCollection zwracał bym IList.

0

@DibbyDum, @teo215 robicie jeden duży serwis czy dzielicie serwis per tabela? A może jeszcze inaczej? Pytam, bo jak tych tabel jest dużo w bazie to per tabela porobi się mnóstwo serwisów.

2

Wiele serwisów, ale nie per tabela tylko per logika biznesowa, takie SRP biznesowe. :D

0

Czyli tak jak się w sumie domyślałem. :) I te serwisy plus to co jest z ORM'a to właśnie nasz model. :)

3

Również podpisuję się pod słowami @DibbyDum
Serwis powinien zwracać IList.Serwis powinien zawierać logikę biznesową a nie operować na pojedynczych tabelach (Wtedy był by tylko nakładą na EF).
Zazwyczaj tworzę kilka mniejszych serwisów gdzie każdy z nich jest odpowiedzialny za konkretną cześć logiki biznesowej.

  • Skoro już masz luźne wiązanie śmiało możesz wstrzyknąć tą zależność za pomocą konstruktora abyś nie tworzył instancji w ramach ViewModelu.
  • Ja jeszcze tworze sobie Interfejs dla ViewModelu. Wykorzystuje ten interfejs w widoku w ramach DesignInstance. Ułatwia mi to tworzenie kodu.
0
teo215 napisał(a):
  • Skoro już masz luźne wiązanie śmiało możesz wstrzyknąć tą zależność za pomocą konstruktora abyś nie tworzył instancji w ramach ViewModelu.

Rozwiń jak możesz. Teraz mam właśnie instancję, nazwijmy to IService w VM.

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