支持字段

支持字段允许 EF 读取和/或写入字段而非属性。 当使用类中的封装来限制对通过应用程序代码访问数据的语义的使用或来增强该语义时,这可能会很有用,但是应该在不使用这些限制/增强的情况下从数据库读取值和/或向数据库写入值。

基本配置

按照约定,将发现下列字段,作为给定属性的支持字段(按优先顺序列出)。

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

在下面的示例中,将 Url 属性配置为将 _url 作为其支持字段:

public class Blog
{
    private string _url;

    public int BlogId { get; set; }

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

请注意,仅为模型中包含的属性发现支持字段。 有关模型中包含哪些属性的详细信息,请参阅“包含和排除属性”。

在字段名称不符合上述约定等情况下,你也可通过使用数据注释Fluent API 来配置支持字段:

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

字段和属性访问

默认情况下,EF 将始终读取并写入支持字段(假设已正确配置了一个支持字段),并且永远不会使用属性。 但是,EF 还支持其他访问模式。 例如,以下示例指示 EF 仅在具体化时写入支持字段,并在所有其他情况下使用属性:

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

有关完整的支持选项集,请参阅 PropertyAccessMode 枚举

仅限字段的属性

你还可以在模型中创建一个概念属性,该属性在实体类中不具有相应的 CLR 属性,而是使用字段来存储实体中的数据。 这不同于阴影属性,后者将数据存储在更改跟踪器中,而不是实体的 CLR 类型中。 当实体类使用方法而非属性来获取/设置值时,或者在域模型中根本不应该公开字段(例如主键)的情况下,通常使用仅限字段的属性。

可通过在 Property(...) API 中提供名称来配置仅限字段的属性:

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 将尝试查找具有给定名称的 CLR 属性,如果找不到属性,则尝试查找一个字段。 如果既找不到属性也找不到字段,则将改为设置一个阴影属性。

你可能需要从 LINQ 查询中引用仅限字段的属性,但此类字段通常是专用的。 可在 LINQ 查询中使用 EF.Property(...) 方法来引用字段:

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