2009-01-05 9 views
8

Obecnie odtwarzam z frameworkiem ASP.Net mvc i kocham go w porównaniu do klasycznego sposobu asp.net. Jedną z rzeczy, o którą się zastanawiam, jest to, czy dopuszczalne jest, aby widok powodował (pośrednio) dostęp do bazy danych?ASP.Net Mvc - Czy funkcja View może wywoływać funkcje, które mogą powodować pobieranie danych?

Na przykład używam kontrolera do zapełnienia niestandardowej klasy danych wszystkimi informacjami, które moim zdaniem View musi wykonać, aby wykonać swoją pracę, jednak podczas przesyłania obiektów do widoku może to spowodować odczytanie bazy danych.

Szybki pseudo przykład.

public interface IProduct 
{ 
    /* Some Members */ 

    /* Some Methods */ 
    decimal GetDiscount(); 
} 

public class Product : IProduct 
{ 
    public decimal GetDiscount(){ ... /* causes database access */ } 
} 

Jeśli View ma dostęp do klasy o produkcie (to zostanie przeniesiony obiekt IProduct), można go nazwać GetDiscount() i dostęp do bazy danych przyczyna.

Zastanawiam się, jak temu zapobiec. Obecnie przechodzę do dziedziczenia z wieloma interfejsami dla klasy Product. Zamiast implementacji tylko IProduct wdroży teraz IProduct i . IProductView wyświetli listę członków klasy, IProduct będzie zawierać wywołania metod, które mogą spowodować dostęp do bazy danych.

"Widok" będzie znać tylko interfejs na klasie i nie będzie mógł wywoływać metod, które powodują dostęp do danych.

Mam inne niejasne przemyślenia na temat "blokowania" obiektu, zanim zostanie on przekazany do widoku, ale mogę przewidzieć ogromny zakres efektów ubocznych za pomocą takiej metody.

Więc moje pytania:

  • czy są jakieś najlepsze praktyki dotyczące tej kwestii?
  • W jaki sposób inne osoby korzystające z MVC powstrzymują widok jako niegrzeczny i robiąc więcej rzeczy niż powinny?

Odpowiedz

3

Twój widok tak naprawdę nie powoduje dostępu do danych. Widok polega po prostu na wywołaniu metody GetDiscount() w interfejsie modelu. Jest to model model, który powoduje dostęp do danych. Rzeczywiście, możesz stworzyć kolejną implementację IProduct, która nie spowodowałaby dostępu do danych, ale nie zmieni się widok.

Obiekty modelu, które leniwy ładowanie niezmiennie powodują dostęp do danych, gdy widok próbuje wyodrębnić dane do wyświetlenia.

To, czy wszystko jest w porządku, zależy od osobistych upodobań i preferencji.

Jednakże, chyba że masz dobry powód do leniwego ładowania, wolałbym załadować dane do obiektu modelu, a następnie przekazać ten "gotowy do pieczenia" dla widoku do wyświetlenia.

+0

Chcę dostarczyć gotowe upieczone dane do widoku, to co robię w kontrolerze (używam budowniczych do tworzenia moich klas modeli widoków), ja (być może przedwcześnie) chcę zaspokoić sytuacje w przyszłości, gdzie mogę chcieć na przykład dostęp do db w transakcji - nie jest łatwo kontrolować w widoku! – Ash

+0

Dla tych gotowych danych nie jest wymagane catering (przepraszam, za okropne kalambur ;-))). Twój widok nie musi być świadomy czegokolwiek - po prostu zużywa obiekt modelu. To zależy od kontrolera i modelu, aby negocjować transakcje itp. Później, jeśli/kiedy jest to wymagane. –

1

Jedną z rzeczy, o których mówię, jest to, czy dopuszczalne jest, aby Widok spowodował (pośrednio) dostęp do bazy danych?

Często zadawałem to samo pytanie. Tak wiele rzeczy, do których uzyskujemy dostęp w modelu w widokach przepełnienia stosu, może powodować niejawny dostęp do bazy danych. To prawie nieuniknione. Chciałbym usłyszeć myśli innych na ten temat.

+1

Model w MVC nie jest potężnym modelem domeny. A przynajmniej tak nie powinno być. Jest to model widoku lekkiego - hierarchia bezpiecznych, spłaszczonych obiektów DTO i innych obiektów prezentacji. Twoje kontrolery i inne usługi tworzą model widoku; widok po prostu go renderuje. –

0

Model nie powinien mieć metod ("czynności"), które składają się z dostępu do danych. To jest obawa DAL. Mógłbyś przechowywać procent procentowy w klasie produktu i mieć metodę GetDiscount zwracającą proste obliczenia, takie jak Cena * (100 - discountPercent) lub coś podobnego.

Odłącz moje jednostki biznesowe (produkt w przykładzie) od dostępu do danych. To jest kwestia repozytorium (w moim przypadku).

+0

Mam metody w moim modelu, aby zapobiec sytuacji, w której niepotrzebnie wykonujesz drogie akcje bazy danych, aby "zapełnić" twój obiekt, zanim pozwolisz, aby jakikolwiek inny kod go dotknął. Co się stanie, jeśli w tej konkretnej sytuacji nigdy nie użyjesz wartości rabatu, a mimo to ją odzyskasz? – Ash

+0

Prawdopodobnie powinienem również dodać, że GetDiscount() jest prawdopodobnie złym wyborem nazwy metody, może GetCategories() może być bardziej odpowiedni. To znaczy. coś bezpośrednio związanego z obiektem, który reprezentuje klasa, ale nie fizycznie jest częścią tabeli bazy danych. – Ash

+0

@Ash: Dla przykładu GetCategories(), wypełniłbym moje dane ViewData obiektem MenuDocument, który zawierał wszystkie informacje niezbędne do renderowania menu kategorii. Sam dokument MenuDocument mógłby zostać wypełniony klasami domen w stylu ActiveRecord. –

1

Jeśli utrzymujesz swoje obiekty domeny "nieustępliwy ignorant", to nie masz tego problemu. Oznacza to, że zamiast mieć getDiscount w klasie produktu, dlaczego nie wystarczy mieć zwykłą właściwość o nazwie Rabat? Zostanie to ustawione przez ORM podczas ładowania instancji klasy Product z bazy danych.

+0

Dokładnie to, co zaproponowałem kilka minut wcześniej ... –

+0

Nawet z POCO, obiekty modelu PI, iteracja i inne operacje na nich mogą powodować działania niepożądane. Uważaj, używając modelu domeny jako modelu widoku. –

0

Zbudowałem witrynę w MonoRail, zanim niekiedy istnieją metody wyzwalające dostęp do danych z widoku. Staram się tego uniknąć, ponieważ gdy się zawiedzie, może się nie udać w sposób nietypowy i nierównomierny (na przykład nie mogę naprawdę spróbować/złapać w szablonie NVelocity). To nie koniec świata - pisałem dobrze wyodrębnione strony PHP od lat, które przeglądały bazę danych i nadal działają wystarczająco dobrze, ponieważ przez większość czasu, jeśli coś się wyda, po prostu przekierowujesz na " Coś nie działa "Strona błędu typu mimo to.

Ale tak, staram się tego uniknąć. W szerszym znaczeniu mój model domeny zazwyczaj nie spływa w dół do widoku. Zamiast tego, widok powoduje, że obiekty Document są bezwstydnie po prostu mocno zapisanymi zrzutami danych, z wszystkimi wstępnie sformatowanymi, bitymi, zmiażdżonymi i czystymi do punktu, w którym widok musi wypluć niektóre ciągi za pomocą niektórych pętli, a jeśli/else, przekształć liczbę "4" w 4-gwiazdkowe obrazy, itp. Dokument ten jest zwykle zwracany przez usługę sieci Web, która znajduje się przed pięknym modelem domeny, lub jest to po prostu prosta struktura, która jest skonstruowana w kontrolerze i przekazywana jako część ViewData. Jeśli obiekt domeny jest używany bezpośrednio, to zwykle nie robi nic, aby jawnie wyzwalać dostęp do danych; obsługiwane przez repozytorium przypominające kolekcję, do którego widok nie ma dostępu, a obiekty domeny zwykle nie mają do niego dostępu.

Ale nie musisz tego robić w ten sposób. Możesz po prostu zostać wystarczająco wyeksponowany, aby po prostu nie wywoływać metod, które dotykają bazy danych z widoku.

+0

Robię hybrydę na tym, ale mam wiele metod pomocniczych widoku, które same mogą formatować dane w oparciu o zawartość dostarczanych obiektów, więc naprawdę nie chcę spłaszczać/formatować danych w kontrolerze - I czuję, że to jest zadanie widzenia! – Ash

+0

@Ash: Uczciwa ocena; znowu, wiele z tego to osobisty gust. Obiekt Dokument zwykle * sam buduje * w oparciu o model domeny, ale obiekt ten jest instancjonowany/konstruowany w kontrolerze. Dla architektury sieciowej uważam, że kontrolerzy nieuchronnie dokonują takiej interpretacji dla widoku. –

+0

To zbliża się do lepszego modelu widoku. Dopóki to podejście jest łatwe do sprawdzenia, wydaje się być w porządku. –

Powiązane problemy