2009-08-11 31 views
7

Moim zdaniem pole ID obiektu biznesowego powinno być tylko do odczytu (publiczne pobranie i prywatny zestaw), ponieważ z definicji identyfikator nigdy się nie zmieni (ponieważ jednoznacznie identyfikuje rekord w bazie danych).Czy identyfikator obiektu biznesowego powinien być tylko do odczytu, czy nie?

Powoduje to problem podczas tworzenia nowego obiektu (identyfikator jeszcze nie ustawiony), zapisz go w bazie danych za pomocą procedury przechowywanej na przykład, która zwraca nowo utworzony identyfikator, a następnie w jaki sposób zapisać go z powrotem w obiekcie, jeśli Właściwość ID jest tylko do odczytu?

Przykład:

Employee employee = new Employee(); 
employee.FirstName="John"; 
employee.LastName="Smith"; 

EmployeeDAL.Save(employee); 

Jak działa metoda Save (które w rzeczywistości łączy się z bazą danych, aby zapisać nowego pracownika) zaktualizować właściwość IDpracownika w obiekcie pracownika, jeśli ta właściwość jest tylko do odczytu (który powinien być ponieważ EmployeeId nigdy się nie zmieni, gdy zostanie utworzony).

Wygląda na to, że Id powinien być zapisywalny przez DAL i tylko do odczytu dla reszty świata. Jak to zaimplementować, szczególnie jeśli klasy DAL i obiekty biznesowe są w różnych złożeniach?

Nie chcę tworzyć metody Save w klasie Employee, ponieważ ta klasa nie powinna mieć nic wspólnego z bazą danych.

+1

Stary problem, dla którego nie wierzę, jest "miła" odpowiedź, a przynajmniej zły kompromis. –

+0

Anthony, usunąłem moją odpowiedź. Myślę, że już się komplikowałem. Zgadzam się z @Martin Brown. Nie ma prostej odpowiedzi na problem. Poszedłbym z tworzeniem nowego obiektu, nawet jeśli oznacza to skopiowanie wszystkich właściwości. –

+0

@Bruno. Już miałem skomentować, że twoja odpowiedź prawdopodobnie zadziała. Wygląda na to, że najlepiej jest zrobić to wewnętrznie: public int Id {get; zestaw wewnętrzny; } W ten sposób tylko DAL będzie mógł go zaktualizować i zezwolić DAL na aktualizację "wewnętrznej" właściwości ID: [assembly: InternalsVisibleTo ("DAL_Assembly")] W ten sposób dla DAL wewnętrzna właściwość ID będzie aktualizowalna . – Anthony

Odpowiedz

2

Innym możliwym rozwiązaniem jest zadeklarować jako pracownika: -

public class Employee 
{ 
    public int Id { get; internal set; } 
} 

... pod warunkiem, że zajęcia pracownicze i DAL są w tym samym zespole

Nie twierdzę się podoba, ale mam Użyj tego.

+0

i jeśli nie są w tym samym zespole, można użyć: [montaż: InternalsVisibleTo ("DAL_Assembly")] – Anthony

0

Jak o:

Employee employee = new Employee(EmployeeDAL.GetNextID()); 

ten powinien również dokonać zapisać kod prostsze.

+1

lub .. Pracownik pracownika = EmployeeDAL.NewEmployee(); –

+0

Tak, wolę rozwiązanie Andry. – DanDan

+0

Dzięki temu rozwiązaniu metoda NewEmployee() natychmiast utworzyłaby nowy rekord w bazie danych. Korzyścią jest to, że będziesz mieć identyfikator EMployeeId, ale co, jeśli użytkownik zdecyduje się nie zapisywać pracownika w końcu? Powinieneś wrócić do bazy danych, aby usunąć rekord, który wydaje się niewłaściwy. – Anthony

1

można dokonać tylko metoda DAL powrócić zaktualizowaną obiektu:

public class EmployeeDAL 
{ 
    Employee EmployeeDAL.Save (Employee employee) 
    { 
     // Save employee 
     // Get the newly generated ID 
     // Recreate the object with the new ID and return it 
    } 
} 

Alternatywnie, można wygenerować nowy identyfikator w kodzie, instancję obiektu z tego identyfikatora następnie zapytać DAL aby go zapisać.

Jeśli chcesz, aby Twój obiekt był aktualizowany podczas operacji zapisu, musisz ustawić tę właściwość jako publiczną.

Ja osobiście lubię tworzyć niezmienne obiekty, które można ustawić tylko raz, przekazując wszystkie wartości do konstruktora. Przy takim podejściu wystarczy utworzyć obiekt do zapisania, a następnie pobrać go z powrotem wraz z przypisanym identyfikatorem z bazy danych i zwrócić go do osoby dzwoniącej.

+0

Co się stanie, jeśli obiekt ma 50 właściwości? Utworzysz nowy obiekt, skopiujesz wartość wszystkich właściwości, abyś mógł zaktualizować właściwość ID. To by działało, ale nie wydaje mi się właściwe. Trwa pobieranie z bazy danych, ale oznacza to, że łączysz się z bazą danych dwa razy: raz, aby zapisać obiekt i raz go odzyskać (gdy już go masz w kodzie klienta). Znowu to nie wydaje się właściwe. – Anthony

+0

Jeśli ma 50 właściwości, użyj czegoś takiego jak http://www.codeplex.com/AutoMapper, aby odwzorować te obiekty z obiektu A na obiekt B –

+0

@Anthony: To prawda. Oto jedna zaleta: po ponownym pobraniu z bazy danych otrzymujesz dokładnie to, co zostało tam zapisane - może ciąg znaków został obcięty lub coś innego. Jeśli popełnisz błąd w kodzie, w aplikacji będziesz wierzył, że masz teraz ten zestaw danych, podczas gdy w rzeczywistości tego nie robisz. Ale znowu, są to różne podejścia projektowe. –

1

Można dokonać setter dla identyfikatora pozwalają ustawić tylko wtedy, gdy nie jest już ustawiony wcześniej:

public class Employee 
{ 
    private int? m_ID; 

    public int? ID 
    { 
     get { return m_ID; } 
     set 
     { 
      if (m_ID.HasValue()) 
       throw ... 
      m_ID = value; 
     } 
    } 
} 

Alternatywnie, myślę, że pewne ramy wsparcia tego typu funkcjonalności (na przykład, myślę, NHibernate będzie pozwala na ustawienie prywatnego settera w polu ID).

+0

Podoba mi się ten pomysł, ale zdasz sobie sprawę, że nie możesz ustawić identyfikatora, jeśli został już ustawiony w czasie wykonywania. Byłoby miło, gdyby w czasie kompilacji właściwość była tylko do odczytu (z wyjątkiem DAL) – Anthony

1

Jak o tylko pozwalając kodu poza DAL odnieść się do obiektu poprzez interfejs, który nie dostarcza setter dla pola ID (i wszelkie inne pola niezmienne):

public interface IEmployee 
{ 
    Int32 Id {get;} 
    String Name {get;set;} 
    // ... and so on ... 
} 

public class Employee: IEmployee 
{ 
    Int32 Id {get;set;} 
    String Name {get;set;} 
} 

DAL może ustawić w razie potrzeby, ale kod zużywający się nie może.

+0

Jak twoja klasa Employee jest publiczna (tak jak powinna być jako DAL, która powinna znajdować się w osobnym zespole musi mieć do niej dostęp), nic nie stoi na przeszkodzie, aby zużywający kod tworzył instancję klasy Employee (a więc i modyfikował ID). – Anthony

Powiązane problemy