Dela via


Nyckellösa entitetstyper

Anmärkning

Den här funktionen lades till under namnet på frågetyper. Den bytte senare namn till nyckellösa entitetstyper.

Förutom vanliga entitetstyper kan en EF Core-modell innehålla nyckellösa entitetstyper, som kan användas för att utföra databasfrågor mot data som inte innehåller nyckelvärden.

Definiera nyckellösa entitetstyper

Nyckellösa entitetstyper kan definieras på följande sätt:

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

Egenskaper för nyckellösa entitetstyper

Nyckellösa entitetstyper stöder många av samma mappningsfunktioner som vanliga entitetstyper, till exempel arvsmappning och navigeringsegenskaper. I relationslager kan de konfigurera måldatabasobjekten och kolumnerna via fluent API-metoder eller dataanteckningar.

De skiljer sig dock från vanliga entitetstyper i och med att de:

  • Det går inte att definiera en nyckel.
  • Spåras aldrig efter ändringar i DbContext och infogas därför aldrig, uppdateras eller tas bort i databasen.
  • Upptäcks aldrig genom konvention.
  • Stöd endast för en delmängd av navigeringsmappningsfunktionerna, särskilt:
    • De får aldrig fungera som det främsta syftet med en relation.
    • ** De kanske saknar navigering till ägda objekt
    • De kan bara innehålla referensnavigeringsegenskaper som pekar på vanliga entiteter.
    • Entiteter får inte innehålla navigeringsegenskaper för nyckellösa entitetstyper.
  • Måste konfigureras med en [Keyless] dataanteckning eller ett .HasNoKey() metodanrop.
  • Kan mappas till en definierande fråga. En definierande fråga är en fråga som deklareras i modellen som fungerar som en datakälla för en nyckellös entitetstyp.
  • Kan ha en hierarki, men den måste mappas som TPH.
  • Det går inte att använda tabelldelning eller entitetsdelning.

Användningsscenarier

Några av de viktigaste användningsscenarierna för nyckellösa entitetstyper är:

  • Fungerar som returtyp för SQL-frågor.
  • Mappa till databasvyer som inte innehåller en primärnyckel.
  • Mappa till tabeller som inte har någon primärnyckel definierad.
  • Mappa till frågor som definierats i modellen.

Mappa till databasobjekt

Mappning av en nyckellös entitetstyp till ett databasobjekt uppnås med hjälp av api:et ToTable eller ToView fluent. Ur EF Core-perspektivet är databasobjektet som anges i den här metoden en vy, vilket innebär att det behandlas som en skrivskyddad frågekälla och inte kan vara målet för uppdaterings-, infognings- eller borttagningsåtgärder. Detta innebär dock inte att databasobjektet faktiskt måste vara en databasvy. Det kan också vara en databastabell som behandlas som endast läsbar. För vanliga entitetstyper förutsätter EF Core däremot att ett databasobjekt som anges i ToTable metoden kan behandlas som en tabell, vilket innebär att det kan användas som en frågekälla men även som mål för åtgärder för uppdatering, borttagning och infogning. I själva verket kan du ange namnet på en databasvy i ToTable och allt bör fungera bra så länge vyn är konfigurerad för att vara uppdaterad i databasen.

Exempel

I följande exempel visas hur du använder nyckellösa entitetstyper för att köra frågor mot en databasvy.

Tips/Råd

Du kan visa den här artikelns exempel på GitHub.

Först definierar vi en enkel blogg- och postmodell:

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; }
}

Därefter definierar vi en enkel databasvy som gör att vi kan köra frågor mot antalet inlägg som är associerade med varje blogg:

await db.Database.ExecuteSqlRawAsync(
    @"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");

Därefter definierar vi en klass för att lagra resultatet från databasvyn:

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

Därefter konfigurerar vi den nyckellösa entitetstypen i OnModelCreating med hjälp av API:et HasNoKey . Vi använder API:et för fluent-konfiguration för att konfigurera mappningen för den nyckellösa entitetstypen:

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

Därefter konfigurerar vi DbContext för att inkludera DbSet<T>:

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

Slutligen kan vi köra frågor mot databasvyn på standard sätt:

var postCounts = await db.BlogPostCounts.ToListAsync();

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

Tips/Råd

Observera att vi också har definierat en frågeegenskap på kontextnivå (DbSet) som fungerar som en rot för frågor mot den här typen.

Tips/Råd

Om du vill testa nyckellösa entitetstyper som mappats till vyer med hjälp av den minnesinterna providern mappar du dem till en fråga via ToInMemoryQuery. Mer information finns i dokumentationen för den minnesinterna leverantören.