Atrybuty mapowania (aka adnotacje danych) dla relacji

Atrybuty mapowania służą do modyfikowania lub zastępowania konfiguracji wykrytej przez konwencje tworzenia modelu. Konfiguracja wykonywana przez atrybuty mapowania może zostać zastąpiona przez interfejs API tworzenia modelu używany w programie OnModelCreating.

Ważne

Ten dokument obejmuje tylko atrybuty mapowania w kontekście konfiguracji relacji. Inne zastosowania atrybutów mapowania zostały omówione w odpowiednich sekcjach szerszej dokumentacji modelowania.

Napiwek

Poniższy kod można znaleźć w pliku MappingAttributes.cs.

Gdzie uzyskać atrybuty mapowania

Wiele atrybutów mapowania pochodzi z przestrzeni nazw System.ComponentModel.DataAnnotations i System.ComponentModel.DataAnnotations.Schema . Atrybuty w tych przestrzeniach nazw są uwzględniane w ramach platformy podstawowej we wszystkich obsługiwanych wersjach platformy .NET, dlatego nie wymagają instalacji żadnych dodatkowych pakietów NuGet. Te atrybuty mapowania są często nazywane "adnotacjami danych" i są używane przez różne struktury, w tym EF Core, EF6, ASP.NET Core MVC itd. Są one również używane do walidacji.

Korzystanie z adnotacji danych w wielu technologiach oraz mapowanie i walidacja doprowadziło do różnic w semantyce między technologiami. Wszystkie nowe atrybuty mapowania przeznaczone dla platformy EF Core są teraz specyficzne dla platformy EF Core, dzięki czemu ich semantyka i używaj prostych i przejrzystych. Te atrybuty znajdują się w pakiecie NuGet Microsoft.EntityFrameworkCore.Abstractions . Ten pakiet jest dołączany jako zależność za każdym razem, gdy jest używany główny pakiet Microsoft.EntityFrameworkCore lub jeden ze skojarzonych pakietów dostawcy bazy danych. Jednak pakiet Abstrakcji jest uproszczonym pakietem, do którego można odwoływać się bezpośrednio za pomocą kodu aplikacji bez wprowadzania wszystkich platform EF Core i jego zależności.

Requiredattribute

RequiredAttribute właściwość jest stosowana do właściwości, aby wskazać, że właściwość nie może być null. W kontekście relacji [Required] jest zwykle używany na właściwości klucza obcego. Dzięki temu klucz obcy nie może być zerowy, co sprawia, że wymagana jest relacja. Na przykład w przypadku następujących typów Post.BlogId właściwość jest niepusta, a relacja staje się wymagana.

public class Blog
{
    public string Id { get; set; }
    public List<Post> Posts { get; } = new();
}

public class Post
{
    public int Id { get; set; }

    [Required]
    public string BlogId { get; set; }

    public Blog Blog { get; init; }
}

Uwaga

W przypadku używania typówBlogId odwołań dopuszczających wartość null w języku C# właściwość w tym przykładzie jest już niepusta, co oznacza, że [Required] atrybut nie będzie miał wpływu.

[Required] nawigowanie zależne ma taki sam efekt. Oznacza to, że klucz obcy jest niepusty, a tym samym co wymaga relacji. Przykład:

public class Blog
{
    public string Id { get; set; }
    public List<Post> Posts { get; } = new();
}

public class Post
{
    public int Id { get; set; }

    public string BlogId { get; set; }

    [Required]
    public Blog Blog { get; init; }
}

Jeśli [Required] znajduje się na nawigacji zależnej, a właściwość klucza obcego jest w stanie cienia, właściwość w tle jest niepusta, co powoduje, że relacja jest wymagana. Na przykład:

public class Blog
{
    public string Id { get; set; }
    public List<Post> Posts { get; } = new();
}

public class Post
{
    public int Id { get; set; }

    [Required]
    public Blog Blog { get; init; }
}

Uwaga

Użycie po [Required] stronie nawigacji głównej relacji nie ma wpływu.

ForeignKeyAttribute

ForeignKeyAttribute służy do łączenia właściwości klucza obcego z jego nawigacjami. [ForeignKey] można umieścić we właściwości klucza obcego z nazwą nawigacji zależnej. Przykład:

public class Blog
{
    public string Id { get; set; }
    public List<Post> Posts { get; } = new();
}

public class Post
{
    public int Id { get; set; }

    [ForeignKey(nameof(Blog))]
    public string BlogKey { get; set; }

    public Blog Blog { get; init; }
}

[ForeignKey] Można również umieścić na nawigacji zależnej lub głównej z nazwą właściwości, która ma być używana jako klucz obcy. Przykład:

public class Blog
{
    public string Id { get; set; }
    public List<Post> Posts { get; } = new();
}

public class Post
{
    public int Id { get; set; }

    public string BlogKey { get; set; }

    [ForeignKey(nameof(BlogKey))]
    public Blog Blog { get; init; }
}

Gdy [ForeignKey] zostanie umieszczony na nawigacji, a podana nazwa nie jest zgodna z żadną nazwą właściwości, zostanie utworzona właściwość w tle o tej nazwie, która będzie pełnić rolę klucza obcego. Przykład:

public class Blog
{
    public string Id { get; set; }
    public List<Post> Posts { get; } = new();
}

public class Post
{
    public int Id { get; set; }

    [ForeignKey("BlogKey")]
    public Blog Blog { get; init; }
}

InversePropertyAttribute

InversePropertyAttribute służy do łączenia nawigacji z odwrotnością. Na przykład w następujących typach jednostek istnieją dwie relacje między Blog i Post. Bez żadnej konfiguracji konwencje EF nie mogą określić, które nawigacje między dwoma typami powinny być sparowane. Dodanie [InverseProperty] do jednej z sparowanych nawigacji rozwiązuje tę niejednoznaczność i umożliwia programowi EF tworzenie modelu.

public class Blog
{
    public int Id { get; set; }

    [InverseProperty("Blog")]
    public List<Post> Posts { get; } = new();

    public int FeaturedPostId { get; set; }
    public Post FeaturedPost { get; set; }
}

public class Post
{
    public int Id { get; set; }
    public int BlogId { get; set; }

    public Blog Blog { get; init; }
}

Ważne

[InverseProperty] jest wymagana tylko wtedy, gdy istnieje więcej niż jedna relacja między tymi samymi typami. W przypadku pojedynczej relacji dwie nawigacje są automatycznie sparowane.

DeleteBehaviorAttribute

Zgodnie z konwencją program EF używa elementu ClientSetNullDeleteBehavior dla relacji opcjonalnych i Cascade zachowania wymaganych relacji. Można to zmienić, umieszczając element DeleteBehaviorAttribute w jednej z nawigacji relacji. Przykład:

public class Blog
{
    public int Id { get; set; }
    public List<Post> Posts { get; } = new();
}

public class Post
{
    public int Id { get; set; }
    public int BlogId { get; set; }

    [DeleteBehavior(DeleteBehavior.Restrict)]
    public Blog Blog { get; init; }
}

Aby uzyskać więcej informacji na temat kaskadowych zachowań, zobacz Usuwanie kaskadowe .