Dela via


Bakgrundsfält

Med bakgrundsfält kan EF läsa och/eller skriva till ett fält i stället för en egenskap. Detta kan vara användbart när inkapsling i klassen används för att begränsa användningen av och/eller förbättra semantiken kring åtkomst till data via programkod, men värdet bör läsas från och/eller skrivas till databasen utan att använda dessa begränsningar/förbättringar.

Grundläggande konfiguration

Enligt konventionen identifieras följande fält som bakgrundsfält för en viss egenskap (listade i prioritetsordning).

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

I följande exempel är egenskapen Url konfigurerad att ha _url som bakgrundsfält:

public class Blog
{
    private string _url;

    public int BlogId { get; set; }

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

Observera att bakgrundsfält endast identifieras för egenskaper som ingår i modellen. Mer information om vilka egenskaper som ingår i modellen finns i Inkludera &exkluderande egenskaper.

Du kan också konfigurera säkerhetskopieringsfält med hjälp av en dataanteckning eller Fluent API, t.ex. om fältnamnet inte motsvarar ovanstående konventioner:

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

Fält- och egenskapsåtkomst

Som standard läser och skriver EF alltid till bakgrundsfältet – förutsatt att ett har konfigurerats korrekt – och använder aldrig egenskapen. EF stöder dock även andra åtkomstmönster. Följande exempel instruerar TILL exempel EF att endast skriva till bakgrundsfältet vid materialisering och att använda egenskapen i alla andra fall:

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

Se PropertyAccessMode-uppräkningen för den fullständiga uppsättningen alternativ som stöds.

Fältegenskaper endast

Du kan också skapa en konceptuell egenskap i din modell som inte har någon motsvarande CLR-egenskap i entitetsklassen, utan i stället använder ett fält för att lagra data i entiteten. Detta skiljer sig från Skuggegenskaper, där data lagras i ändringsspåraren i stället för i entitetens CLR-typ. Endast fältegenskaper används ofta när entitetsklassen använder metoder i stället för egenskaper för att hämta/ange värden, eller i fall där fält inte ska exponeras alls i domänmodellen (t.ex. primära nycklar).

Du kan konfigurera en egenskap endast för fält genom att ange ett namn i API:et 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 försöker hitta en CLR-egenskap med det angivna namnet, eller ett fält om en egenskap inte hittas. Om varken en egenskap eller ett fält hittas konfigureras en skuggegenskap i stället.

Du kan behöva referera till en endast fältegenskap från LINQ-frågor, men sådana fält är vanligtvis privata. Du kan använda EF.Property(...) metoden i en LINQ-fråga för att referera till fältet:

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