A legtöbb modern relációs adatbázis rendelkezik már JSON támogatással, ami lehetőséget ad arra, hogy a tábla oszlopaiban JSON dokumentumokat tároljunk és ezekre szűrjünk úgy, mintha a tábla részei lennének. Ezzel a megoldással ötvözhető a racionális és a dokumentum alapú adatbázisok előnye.
Az Entity Framework a 7.0-tól támogatja ezen funkciót agnosztikus módon, vagyis nem kell, hogy a DB natÃvan tudja a funkciót. Azon DB megoldások esetén, ahol ez natÃvan nem támogatott, ott az Entity Framework oldja ezt meg. De milyen elÅ‘nye is van a hibrid tárolásnak?
Tételezzük fel, hogy rendelések adatait kell tárolnunk. Minden rendeléshez tartozik egy számlázási és egy szállÃtási cÃm. Ideális esetben ezek megegyeznek, de elÅ‘fordulhat, hogy nem, vagyis két cÃmet kell tárolnunk. A cÃm pedig egy összetett tÃpus. Rendelkezik utca, házszám, irányÃtószám, város és ország azonosÃtóval. Ennek a modellezéséhez a normalizálás szabályait betartva külön táblát kellene felvennünk a cÃmek tárolásához, aminek az elemeire a rendelés táblából egy külsÅ‘ kulcs segÃtségével hivatkoznánk.
Ez azt jelentené, hogy olvasáskor minimum két táblából kellene lekérdeznünk join művelet segÃtségével, ami bonyolÃtja a lekérdezéseket. A nagyobb baj viszont akkor van, ha többet olvassuk az adatbázist, mint Ãrjuk. Ebben az esetben minél több táblánk van, annál lassabban tudunk olvasni, hiszen több tábla adatát kell beolvasnia a rendszernek.
És akkor még a változásokról nem is beszéltünk. Mi van akkor, ha a rendszerünk szállÃt külföldre is, ahol egy más cÃmformátum alkalmazott?
Ez csak egyetlen egy alkalmazási terület, de alapvetÅ‘en összetett tÃpusok modellezése esetén jön jól a JSON támogatás.
Nézzünk egy példát. Tételezzük fel, hogy a szerzÅ‘t ki szeretnénk egészÃteni kapcsolati adatokkal, amit az alábbi módon modellezünk:
public class ContactDetails
{
public Address Address { get; set; } = null!;
public string? Phone { get; set; }
}
public class Address
{
public string Street { get; set; }
public string City { get; set; }
public string Postcode { get; set; }
public string Country { get; set; }
}
public class Author
{
public int Id { get; set; }
public string Name { get; set; }
public ContactDetails Contact { get; set; }
}
Ebben a modellben ez tradicionálisan három táblát jelentene. Azonban ha azt szeretnénk elérni, hogy az Author táblában a ContactDetails egy JSON oszlop legyen, akkor az OnModelCreating-ben a DBContext esetén az alábbi konfigurációt kell megadnunk:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Author>().OwnsOne(
author => author.Contact, ownedNavigationBuilder =>
{
ownedNavigationBuilder.ToJson();
ownedNavigationBuilder.OwnsOne(contactDetails => contactDetails.Address);
});
}
Az OwnsOne vagy OwnsMany a kapcsolat tÃpusát konfigurálja, hogy egy az egyhez vagy egy a többhöz kapcsolatról beszélünk. A ToJson hÃvás azt jelzi, hogy az összerendelés JSON tárolással történjen.
Ezt követÅ‘en lekérdezésekben és mentésekkor nincs mit módosÃtanunk, ugyan úgy működnek a lekérdezések, mint eddig, csak a háttérben bizonyos oszlopok JSON objektumok formájában tárolódnak.