Champs de stockage

Les champs de stockage permettent à EF de lire et/ou d’écrire dans un champ plutôt que dans une propriété. Cela peut être utile lorsqu’une encapsulation dans la classe est utilisée pour restreindre l’utilisation et/ou améliorer la sémantique autour de l’accès à la base de données par un code d’application, mais que la valeur doit être lue à partir de ou écrite dans la base de données sans utiliser ces restrictions/améliorations.

Configuration de base

Par convention, les champs suivants sont détectés comme champs de stockage pour une propriété donnée (répertoriés dans l’ordre de priorité).

  • <camel-cased property name>
  • _<camel-cased property name>
  • _<property name>
  • m_<camel-cased property name>
  • m_<property name>

Dans l’exemple suivant, la propriété Url est configurée pour avoir _url en tant que son champ de stockage :

public class Blog
{
    private string _url;

    public int BlogId { get; set; }

    public string Url
    {
        get { return _url; }
        set { _url = value; }
    }
}

Notez que les champs de stockage sont uniquement détectés pour des propriétés incluses dans le modèle. Si vous souhaitez obtenir plus d’informations sur les propriétés qui sont incluses dans le modèle, consultez Inclure et exclure des propriétés.

Vous pouvez également configurer des champs de stockage en utilisant des Annotations de données ou l’API Fluent, par exemple si le nom de champ ne correspond pas aux conventions ci-dessus :

public class Blog
{
    private string _validatedUrl;

    public int BlogId { get; set; }

    [BackingField(nameof(_validatedUrl))]
    public string Url
    {
        get { return _validatedUrl; }
    }

    public void SetUrl(string url)
    {
        // put your validation code here

        _validatedUrl = url;
    }
}

Accès à la propriété et au champ

Par défaut, EF lit et écrit toujours dans le champ de stockage, en supposant que l’opération a été correctement configurée et n’utilise jamais la propriété. Toutefois, EF prend également en charge d’autres modèles d’accès. Par exemple, l’exemple suivant instruit à EF d’écrire dans le champ de stockage uniquement lors de la matérialisation et d’utiliser la propriété dans tous les autres cas :

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .Property(b => b.Url)
        .HasField("_validatedUrl")
        .UsePropertyAccessMode(PropertyAccessMode.PreferFieldDuringConstruction);
}

Consultez l’Énumération PropertyAccessMode pour découvrir l’ensemble complet d’options prises en charge.

Propriétés de champ uniquement

Vous pouvez également créer une propriété conceptuelle dans votre modèle qui ne dispose pas d’une propriété CLR correspondante dans la classe entité, mais utilise à la place un champ pour stocker les données dans l’entité. C’est une opération différente des Propriétés fantômes dans lesquelles les données sont stockées dans le dispositif de suivi des changements, plutôt que dans le type de CLR de l’entité. Les propriétés de champ uniquement sont habituellement utilisées lorsque la classe d’entité utilise des méthodes au lieu de propriétés pour obtenir/définir des valeurs ou dans les cas où les champs ne doivent pas être exposés du tout dans le modèle de domaine (par exemple, des clés primaires).

Vous pouvez configurer une propriété de champ uniquement en fournissant un nom dans l’API Property(...) :

internal class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .Property("_validatedUrl");
    }
}

public class Blog
{
    private string _validatedUrl;

    public int BlogId { get; set; }

    public string GetUrl()
    {
        return _validatedUrl;
    }

    public void SetUrl(string url)
    {
        using (var client = new HttpClient())
        {
            var response = client.GetAsync(url).Result;
            response.EnsureSuccessStatusCode();
        }

        _validatedUrl = url;
    }
}

EF tente de rechercher une propriété CLR ayant le nom donné ou un champ si une propriété est introuvable. Si une propriété ou un champ sont introuvables, une propriété fantôme est configurée à la place.

Il est possible que vous deviez vous référer à une propriété de champ uniquement à partir de requêtes LINQ, mais de tels champs sont généralement privés. Vous pouvez utiliser la méthode EF.Property(...) dans une requête LINQ pour faire référence à ce champ :

var blogs = db.blogs.OrderBy(b => EF.Property<string>(b, "_validatedUrl"));