Łączenie wielu tabel za pomocą NHibernate QueryOver
NHibernate to popularny framework ORM (Object-Relational Mapping) dla platformy .NET, który umożliwia programistom interakcję z bazami danych za pomocą obiektów .NET. Jedną z kluczowych operacji podczas pracy z bazami danych jest łączenie (ang. join) wielu tabel w celu pobrania powiązanych danych. QueryOver to oparta na Fluent API składnia zapytań w NHibernate, która zapewnia bardziej intuicyjny i bezpieczny typowo sposób konstruowania zapytań SQL. Metoda JoinAlias
jest kluczowa w QueryOver do definiowania relacji między tabelami i umożliwia łączenie wielu encji na podstawie ich powiązań.
Poniżej przedstawiono przykład łączenia czterech powiązanych ze sobą encji: Person
, PersonFavorites
, PersonCompany
i Company
.
Definicje encji:
public class Person
{
public virtual int Id { get; set; }
public virtual ICollection<PersonFavorites> Favorites { get; set; }
public virtual ICollection<PersonCompany> Companies { get; set; }
}
public class PersonFavorites
{
public virtual Person Person { get; set; }
public virtual Favorite Favorite { get; set; }
}
public class PersonCompany
{
public virtual Person Person { get; set; }
public virtual Company Company { get; set; }
}
public class Company
{
public virtual int Id { get; set; }
// Inne właściwości...
}
public class Favorite
{
public virtual int Id { get; set; }
// Inne właściwości...
}
Zapytanie z użyciem QueryOver:
Person personAlias = null;
PersonFavorites personFavoriteAlias = null;
PersonCompany personCompanyAlias = null;
Company companyAlias = null;
var query = session.QueryOver<Person>(() => personAlias)
.JoinAlias(() => personAlias.Favorites, () => personFavoriteAlias)
.JoinAlias(() => personAlias.Companies, () => personCompanyAlias)
.JoinAlias(() => personCompanyAlias.Company, () => companyAlias)
.Where(() => personCompanyAlias.Person.Id == 123) // Przykład warunku
.List<Person>();
W tym przykładzie, za pomocą metody JoinAlias
, łączymy encję Person
z kolekcją Favorites
poprzez alias personFavoriteAlias
, następnie z kolekcją Companies
poprzez alias personCompanyAlias
, a na końcu łączymy PersonCompany
z Company
poprzez alias companyAlias
. Klauzula Where
filtruje wyniki, wybierając tylko te osoby, dla których Id
w tabeli PersonCompany
wynosi 123.
Dodatkowe scenariusze użycia JoinAlias
:
-
Pobieranie ulubionych produktów użytkownika wraz z informacjami o firmie, która je oferuje: Załóżmy, że mamy encje
User
,UserFavoriteProduct
,Product
iSupplier
. Możemy użyćJoinAlias
do pobrania wszystkich ulubionych produktów danego użytkownika wraz z nazwą dostawcy każdego produktu.```csharp User userAlias = null; UserFavoriteProduct userFavoriteAlias = null; Product productAlias = null; Supplier supplierAlias = null;
var favoriteProducts = session.QueryOver
(() => userAlias) .JoinAlias(() => userAlias.FavoriteProducts, () => userFavoriteAlias) .JoinAlias(() => userFavoriteAlias.Product, () => productAlias) .JoinAlias(() => productAlias.Supplier, () => supplierAlias) .Where(() => userAlias.Id == currentUserId) .Select( Projections.Property(() => productAlias.Name), Projections.Property(() => supplierAlias.Name) ) .List -
Wyświetlanie wszystkich zamówień złożonych przez klientów z określonego miasta wraz z informacjami o produktach w tych zamówieniach: Mając encje
Customer
,Order
,OrderItem
iProduct
, możemy połączyć te tabele, aby znaleźć wszystkie zamówienia klientów z danego miasta i wyświetlić nazwy produktów w każdym zamówieniu.```csharp Customer customerAlias = null; Order orderAlias = null; OrderItem orderItemAlias = null; Product productAlias = null;
var customerOrders = session.QueryOver
(() => customerAlias) .JoinAlias(() => customerAlias.Orders, () => orderAlias) .JoinAlias(() => orderAlias.OrderItems, () => orderItemAlias) .JoinAlias(() => orderItemAlias.Product, () => productAlias) .Where(() => customerAlias.City == "Warszawa") .SelectList(list => list .Select(() => customerAlias.Name).WithAlias(() => new { CustomerName = default(string) }) .Select(() => orderAlias.OrderDate).WithAlias(() => new { OrderDate = default(DateTime) }) .Select(() => productAlias.Name).WithAlias(() => new { ProductName = default(string) }) ) .List (); ``` -
Znalezienie wszystkich pracowników należących do działów zlokalizowanych w konkretnym budynku: Przy założeniu istnienia encji
Employee
,Department
iBuilding
, możemy połączyć te tabele, aby znaleźć wszystkich pracowników pracujących w działach znajdujących się w określonym budynku.```csharp Employee employeeAlias = null; Department departmentAlias = null; Building buildingAlias = null;
var employeesInBuilding = session.QueryOver
(() => employeeAlias) .JoinAlias(() => employeeAlias.Department, () => departmentAlias) .JoinAlias(() => departmentAlias.Building, () => buildingAlias) .Where(() => buildingAlias.Address.Contains("ul. Nowa")) .List (); ```
Metoda JoinAlias
w NHibernate QueryOver jest potężnym narzędziem do efektywnego łączenia wielu powiązanych tabel i pobierania złożonych zestawów danych w sposób obiektowy i typowo bezpieczny. Umożliwia tworzenie czytelnych i łatwych w utrzymaniu zapytań, które odzwierciedlają relacje między encjami w bazie danych.