Typy jednostek bez kluczy

Uwaga

Ta funkcja została dodana pod nazwą typów zapytań. Później zmieniono nazwę na typy jednostek bez klucza.

Oprócz zwykłych typów jednostek model EF Core może zawierać bezkluczowe typy jednostek, które mogą służyć do wykonywania zapytań bazy danych względem danych, które nie zawierają wartości kluczy.

Definiowanie typów jednostek bez klucza

Typy jednostek bez klucza można zdefiniować w następujący sposób:

[Keyless]
public class BlogPostsCount
{
    public string BlogName { get; set; }
    public int PostCount { get; set; }
}

Cechy typów jednostek bez klucza

Typy jednostek bez klucza obsługują wiele z tych samych możliwości mapowania co zwykłe typy jednostek, takie jak mapowanie dziedziczenia i właściwości nawigacji. W magazynach relacyjnych mogą konfigurować docelowe obiekty i kolumny bazy danych za pomocą płynnych metod interfejsu API lub adnotacji danych.

Różnią się one jednak od zwykłych typów jednostek w następujących typach:

  • Nie można zdefiniować klucza.
  • Nigdy nie są śledzone pod kątem zmian w obiekcie DbContext i dlatego nigdy nie są wstawiane, aktualizowane ani usuwane w bazie danych.
  • Nigdy nie są odnajdywane zgodnie z konwencją.
  • Obsługuje tylko podzbiór możliwości mapowania nawigacji, w szczególności:
    • Nigdy nie mogą działać jako główny koniec relacji.
    • Mogą nie mieć nawigacji do jednostek będących własnością
    • Mogą zawierać tylko właściwości nawigacji referencyjnej wskazujące zwykłe jednostki.
    • Jednostki nie mogą zawierać właściwości nawigacji do typów jednostek bez klucza.
  • Należy skonfigurować adnotację [Keyless] danych lub wywołanie .HasNoKey() metody.
  • Może zostać zamapowany na zapytanie definiujące. Zapytanie definiujące to zapytanie zadeklarowane w modelu, które działa jako źródło danych dla typu jednostki bez klucza.
  • Może mieć hierarchię, ale musi być mapowana jako TPH.
  • Nie można użyć dzielenia tabeli lub dzielenia jednostek.

Scenariusze użytkowania

Niektóre z głównych scenariuszy użycia typów jednostek bez klucza to:

  • Obsługa jako typ zwracany dla zapytań SQL.
  • Mapowanie na widoki bazy danych, które nie zawierają klucza podstawowego.
  • Mapowanie na tabele, które nie mają zdefiniowanego klucza podstawowego.
  • Mapowanie na zapytania zdefiniowane w modelu.

Mapowanie na obiekty bazy danych

Mapowanie typu jednostki bez klucza na obiekt bazy danych jest osiągane przy użyciu interfejsu API lub ToView płynnegoToTable. Z perspektywy programu EF Core obiekt bazy danych określony w tej metodzie jest widokiem, co oznacza, że jest traktowany jako źródło zapytania tylko do odczytu i nie może być celem operacji aktualizacji, wstawiania lub usuwania. Nie oznacza to jednak, że obiekt bazy danych jest rzeczywiście wymagany do wyświetlania bazy danych. Alternatywnie może to być tabela bazy danych, która będzie traktowana jako tylko do odczytu. Z drugiej strony w przypadku zwykłych typów jednostek program EF Core zakłada, że obiekt bazy danych określony w ToTable metodzie może być traktowany jako tabela, co oznacza, że może być używany jako źródło zapytania, ale także celem operacji aktualizacji, usuwania i wstawiania. W rzeczywistości można określić nazwę widoku ToTable bazy danych i wszystko powinno działać prawidłowo, o ile widok jest skonfigurowany do aktualizowania w bazie danych.

Przykład

W poniższym przykładzie pokazano, jak używać typów jednostek bez klucza do wykonywania zapytań względem widoku bazy danych.

Napiwek

Przykład z tego artykułu można zobaczyć w witrynie GitHub.

Najpierw definiujemy prosty model Blog i Post:

public class Blog
{
    public int BlogId { get; set; }
    public string Name { get; set; }
    public string Url { get; set; }
    public ICollection<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public int BlogId { get; set; }
}

Następnie zdefiniujemy prosty widok bazy danych, który pozwoli nam wykonywać zapytania dotyczące liczby wpisów skojarzonych z każdym blogiem:

db.Database.ExecuteSqlRaw(
    @"CREATE VIEW View_BlogPostCounts AS
                SELECT b.Name, Count(p.PostId) as PostCount
                FROM Blogs b
                JOIN Posts p on p.BlogId = b.BlogId
                GROUP BY b.Name");

Następnie zdefiniujemy klasę do przechowywania wyniku z widoku bazy danych:

public class BlogPostsCount
{
    public string BlogName { get; set; }
    public int PostCount { get; set; }
}

Następnie skonfigurujemy typ jednostki bez klucza w pozycji OnModelUtwórz przy użyciu interfejsu HasNoKey API. Interfejs API płynnej konfiguracji służy do konfigurowania mapowania dla typu jednostki bez klucza:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder
        .Entity<BlogPostsCount>(
            eb =>
            {
                eb.HasNoKey();
                eb.ToView("View_BlogPostCounts");
                eb.Property(v => v.BlogName).HasColumnName("Name");
            });
}

Następnie skonfigurujemy element DbContext tak, aby zawierał element DbSet<T>:

public DbSet<BlogPostsCount> BlogPostCounts { get; set; }

Na koniec możemy wykonywać zapytania dotyczące widoku bazy danych w standardowy sposób:

var postCounts = db.BlogPostCounts.ToList();

foreach (var postCount in postCounts)
{
    Console.WriteLine($"{postCount.BlogName} has {postCount.PostCount} posts.");
    Console.WriteLine();
}

Napiwek

Należy pamiętać, że zdefiniowaliśmy również właściwość zapytania na poziomie kontekstu (DbSet), która będzie pełnić rolę katalogu głównego dla zapytań względem tego typu.

Napiwek

Aby przetestować typy jednostek bez klucza mapowane na widoki przy użyciu dostawcy w pamięci, zamapuj je na zapytanie za pomocą metody ToInMemoryQuery. Aby uzyskać więcej informacji, zobacz dokumentację dostawcy w pamięci.