1.4.13 支持字段

优质
小牛编辑
112浏览
2023-12-01

支持字段允许 EF 直接读写字段(而不是属性)。

惯例

按照惯例,以下字段将被发现为给定属性的支持字段(按列出顺序优先)。只有包含在模型中的属性才具有支持字段。关于属性如何包含在模型中,请查看 包含和排除属性。

  • _<驼峰属性名>
  • _<属性名>
  • m_<驼峰属性名>
  • m_<属性名>
public class Blog
{
    private string _url;

    public int BlogId { get; set; }

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

配置了支持字段后,EF 将会在从数据库填充实体实例时直接写入字段(而不是 setter 属性访问器),之后 EF 将会尽量使用属性来读写该值。例如,如果 EF 要为属性更新该值,它将使用已定义的 setter 属性访问器。当然,如果属性是只读的,EF 则会直接将值写入支持字段。

数据注解

不能使用数据注解来配置支持字段。

流式 API

可以使用流式 API 来为属性配置支持字段。

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

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

public class Blog
{
    private string _validatedUrl;

    public int BlogId { get; set; }

    public string Url
    {
        get { return _validatedUrl; }
    }

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

        _validatedUrl = url;
    }
}

支持字段使用控制

可以配置 EF 对支持字段或属性的使用模式。查看 PropertyAccessMode 枚举 以了解支持的选项。

modelBuilder.Entity<Blog>()
    .Property(b => b.Url)
    .HasField("_validatedUrl")
    .UsePropertyAccessMode(PropertyAccessMode.Field);

无属性字段

还可以在模型中创建一个在实体类型中没有对应属性的属性,它通过字段在实体中存储数据。这与 影子属性 不同,影子属性的数据存储在变更跟踪器里面。这通常被用于实体类型通过方法来获取/设置值的情况。

可以使用 Property(...) API 告诉 EF 字段的名称。如果不存在给定名称的属性,则 EF 就会查找该名称的字段。

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

还可以选择给定属性名,而不是字段名。该名称将在创建模型时用到,尤其是用作映射到数据库中的数据列名称的时候。

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

当实体类型中没有对应的属性时,你可以在 LINQ 中使用 EF.Property(...) 方法来引用该属性,因为在概念上它是模型的一部分。

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