Value Object w Bazie danych

0

Witam.
Piszę aplikację w c# wykorzystując entity framework i mvc. Do tego używam koncepcji DDD. I tutaj jest moje pytanie. Mam klasę Bulding, która jest korzeniem agregatu oraz address, który jest value object, czyli nie posiada ID. Przez to entity framework nie wie jak ma to traktować. Co zrobić w takim wypadku, aby została dobrze zbudowana baza danych? Czytałam, że są dwie opcje i, że można zrobić z tego osobną encję w bazie danych, a w aplikacji ukryć to id jakoś, ale nie bardzo wiem jak to zrobić.

moje klasy:

public class Building : EntityDbManaged
{

    public String DepartmentName { get; set; }
    public AddressData Address { get;  set; }

    public virtual ICollection<Floor> Floors { get; set; }
}

public class AddressData : ValueObject<AddressData>
{

    private readonly String _streetWithNumber;
    private readonly String _city;
    private readonly String _region;
    private readonly String _country;
    private readonly String _postalCode;

    public AddressData(String street, String city, String region, String country, String postalCode)
    {
        _streetWithNumber = street;
        _city = city;
        _region = region;
        _country = country;
        _postalCode = postalCode;


    }

no i w kontekście mam na razie:
public DbSet<Building> Buildings { get; set; }

0

Poczytaj o atrybucie ComplexType w EF, pola twojej klasy AddressData zostana w bazie zmapowane jako pola encji Building.

0

Oznacz AddressData atrybutem [ComplexType], bo tak to się w EF nazywa.

0

Dzięki wielkie za odpowiedzi!
Tylko problem dalej występuje. teraz pojawia mi się inner exepction: No mapping specified for properties Building.Address in Set Buildings.\r\nAn Entity with Key (PK) will not round-trip when:\r\n Entity is type [Data.Contexts.Building]\r\n"

a w internecie znalazłam, że to powinno się robic z automatu:
"Code First has a concept of Complex Type Discovery that works based on a set of Conventions. The convention is that if Code First discovers a class where a primary key cannot be inferred, and no primary key is registered through Data Annotations or the fluent API, then the type will be automatically registered as a complex type. Complex type detection also requires that the type does not have properties that reference entity types (i.e. all the properties must be scalar types) and is not referenced from a collection property on another type."

0

@Sylwiaaaa
Encja 'AddressData' nie posiada żadnej publicznej właściwości. Entity Framework takiej encji nie zmapuje, stąd błąd.

0

@Sylwiaaaa
Byłbym zapomniał... klasa 'AddressData' nie posiada również domyślnego bezparametrowego konstruktora. Takiej klasy też nie użyjesz jako encji bazodanowej.

0

Dzięki! Tylko jeśli to nie jest korzeń agregatu, to nie powinien mieć pól prywatnych żeby był dostęp tylko przez korzeń? I jak to pogodzić w takim razie z bazą danych?

0

A, chyba że jak zrobię public readonly i private set to będzie okej?

0

Jeśli EF czegoś nie potrafi, to zawsze można użyć normalnego ORMa. ;)

0
Sylwia1992 napisał(a):

Dzięki! Tylko jeśli to nie jest korzeń agregatu, to nie powinien mieć pól prywatnych żeby był dostęp tylko przez korzeń? I jak to pogodzić w takim razie z bazą danych

Nie, nie... Ani pojęcie 'Encji' ani 'Korzenia Agregatu' nie nakłada restrykcji co do poziomu enkapsulacji zawartości. Agregat w koncepcji Domain Driven Development jest to wydzielony obszar domeny biznesowej (reprezentowany przez zestaw encji) który powinien być traktowany jako całość zarówno z punktu widzenia dostępu do danych (persystencji obiektów domeny) jak i procesów biznesowych. Korzeń agregatu w tym przypadku jest wyszczególnioną encją za pomocą której powinno odbywać się wykonywanie operacji odczytu/zapisu przez warstwę dostępu do danych (tzw. Data Access Layer) na całym agregacie. Tak więc na encjach które nie są korzeniami nie powinno być możliwe bezpośrednie wykonanie takich operacji. Ale myślę, że to już wiesz skoro bierzesz się za ten temat.

Sylwiaaa napisał(a):

A, chyba że jak zrobię public readonly i private set to będzie okej?

Nie biędzie ok:

  1. Właściwość nie może być read-only. Atrybut ten może być nałożony tylko na proste pola a te nie są mapowane na kolumny w bazie danych.
  2. Właściwość musi mieć publiczny getter.
  3. Właściwość może mieć prywatny setter - Entity Framework sobie z tym poradzi (wstrzyknie wartość przez refleksję). Przydatne np: przy enkapsulacji kolekcji.
somekind napisał(a):

Jeśli EF czegoś nie potrafi, to zawsze można użyć normalnego ORMa. ;)

Mam nadzieję, że nie masz na myśli NHibernate... ;)

0

W ogolnosci DDD nie zaklada ze encje bazodanowe = obiekty bazodanowe. ORM'y maja czesto rozne ograniczenia w tym dot. modyfikatorow dostepu do pól/wlasciwosci.
Wiec albo sie godzimy z tymi ograniczeniami albo operujemy na obiektach czysto biznesowych, ktore w momencie zapisu sa mapowane z modelu biznesowego na model bazodanowy i wtedy zapisywane.
Pytanie tylko, czy to ma sens. ORMy powstaly zeby ulatwiac zycia, a nie utrudniac. Osoboscie, wole pogodzic sie wiec z pewnymi niedoskonalosciami niz utrzymywac jednoczesnie dwa modele (biznesowy i bazodanowy).

Na poczatku mialo byc :
*W ogolnosci DDD nie zaklada ze encje bazodanowe = obiekty biznesowe

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