Jedna encja czy dwie?

0

Mam aplikację do trzymania i dzielenia się plikami. Użytkownicy mogą tworzyć grupy. Użytkownicy mogą też przyznawać dostęp innym użytkownikom do swoich plików. Zależnie od tego, czy plik jest prywatny, czy należy do grupy, zasady dostępu są inne. Tak to wygląda:

public class File
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public int Size { get; set; }
        public string OwnerId { get; set; } // jeśli plik prywatny
        public int DirectoryId { get; set; }
        public int? GroupId { get; set; }
        public DateTime CreatedAt { get; set; }
        public DateTime? LastUpdatedAt { get; set; }

        public User Owner { get; set; }
        public Directory Directory { get; set; }
        public Group Group { get; set; }
        public ICollection<Access> Accesses { get; set; }
        
        // jakieś metody odpytujące stan obiektu
    }

Model jest anemiczny, jak widać. Mimo to chciałbym mieć w tej klasie File jakieś metody typu HasUserAccess(string userId), aby nie wypychać sztucznie całej logiki do warstwy wyżej. Problem w tym, że jeśli tak ma być, to muszę pobierać nadmiarowe dane (np. plik prywatny nie potrzebuje danych o grupie, w której istnieje, i o jej członkach). Rozwiązaniem jest lazy loading, ale on jest teraz chyba niezalecany w świecie EF Core ze względu na problemy, które powoduje. Pytanie: czy encja File powinna być rozbita na UserFile i GroupFile z własnymi tabelami i klasami do zapisu i odczytu?

0

Jeśli masz w encji część pól/metod zależną od wartości jakiegoś pola, które określa typ danej encji, to dziedziczenie pewnie by było najlepsze w tym wypadku. Możesz spróbować z Class Table Inheritance.

0

W EFC jest tylko coś takiego jak Table Per Hierarchy: https://www.learnentityframeworkcore.com/inheritance
One table is used to represent all classes in the hierarchy. A "discriminator" column is used to discriminate between differing types.

Nie wiem dokładnie o co chodzi z Class Table Inheritance. Tu: https://martinfowler.com/eaaCatalog/classTableInheritance.html znalazłem: Class Table Inheritance supports this by using one database table per class in the inheritance structure. I jak to wygląda? Jeśli mam klasę A : B, to mam tabelki A, B i jeśli chcę pobrać dane o A, to pobieram rekord z B i robię joina z rekordem z A?

0

W ef masz rozne encje a w bazie jedna tabele. Ef uzywa tzw dyscriminator. Bardzo fajne rozwiazanie. Nie wiem czy akurat w twoim przpadku zasadne ale mozesz sprobowac

0

@szydlak Wiem, ale chyba o coś innego chodziło z tym Class Table Inheritance. Tak czy inaczej, poszedłbyś w dwie encje?

1

Tak bym to chyba zamodelował. Czyli klasa abstrakcyjna File. I z niej dziedziczą GroupFile, oraz UserFile. W EF konfigurujesz TPH. I z poziomu kodu masz dostęp do różnych klas w EF ale w bazie jest jedna tabela File z kolumną Discriminator. Ale musisz przemyśleć sam czy to nie stworzy Ci potem problemów

2

Nie szedłbym w dwie encje, przy zmianie pliku istniejącego z prywatnego na grupowy, to co, tworzymy nowym plik z nowym idkiem w drugiej tabeli ;)?

Lazy Loading jest jak najbardziej jednym z rozwiązań, a to że niektórzy nie umieją z niego korzystać nie czyni go od razu nie zalecanym mechanizmem.

PS: ja tam w ogóle bym dał tylko idki, a nie referencje do encji :D

0

@neves A dlaczego tylko idki?

0

@Juhas Ok, ale jak nie lazy loading, to co? W CRUDzie dla UserFile i GroupFile jakieś 80% kodu się powtarza. Co jeśli miałbym więcej niż 2 rodzaje encji, np. 100 rodzajów produktów w sklepie?

EDIT: Chyba zostanę przy lazy loading. Znalazłem post somekinda o tym: https://4programmers.net/Forum/1246012

2

Powiadam Ci, nie mieszaj modelu domenowego, gdzie sprawdzasz poprawność reguł biznesowych z modelem do odczytu zoptymalizowanym pod agregacje, projekcje. Zobacz jakie warunki musisz sprawdzić przy zapisie, tabelki i lazy loadingi to już kwestia na później. To co widać na GUI wcale nie musi iść z tabelki.

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