• 支持字段
    • 惯例
    • 数据注解
    • 流式 API
      • 支持字段使用控制
      • 无属性字段

    支持字段

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

    惯例

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

    • _<驼峰属性名>
    • _<属性名>
    • m_<驼峰属性名>
    • m_<属性名>
    1. public class Blog
    2. {
    3. private string _url;
    4. public int BlogId { get; set; }
    5. public string Url
    6. {
    7. get { return _url; }
    8. set { _url = value; }
    9. }
    10. }

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

    数据注解

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

    流式 API

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

    1. class MyContext : DbContext
    2. {
    3. public DbSet<Blog> Blogs { get; set; }
    4. protected override void OnModelCreating(ModelBuilder modelBuilder)
    5. {
    6. modelBuilder.Entity<Blog>()
    7. .Property(b => b.Url)
    8. .HasField("_validatedUrl");
    9. }
    10. }
    11. public class Blog
    12. {
    13. private string _validatedUrl;
    14. public int BlogId { get; set; }
    15. public string Url
    16. {
    17. get { return _validatedUrl; }
    18. }
    19. public void SetUrl(string url)
    20. {
    21. using (var client = new HttpClient())
    22. {
    23. var response = client.GetAsync(url).Result;
    24. response.EnsureSuccessStatusCode();
    25. }
    26. _validatedUrl = url;
    27. }
    28. }

    支持字段使用控制

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

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

    无属性字段

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

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

    1. class MyContext : DbContext
    2. {
    3. public DbSet<Blog> Blogs { get; set; }
    4. protected override void OnModelCreating(ModelBuilder modelBuilder)
    5. {
    6. modelBuilder.Entity<Blog>()
    7. .Property("_validatedUrl");
    8. }
    9. }
    10. public class Blog
    11. {
    12. private string _validatedUrl;
    13. public int BlogId { get; set; }
    14. public string GetUrl()
    15. {
    16. return _validatedUrl;
    17. }
    18. public void SetUrl(string url)
    19. {
    20. using (var client = new HttpClient())
    21. {
    22. var response = client.GetAsync(url).Result;
    23. response.EnsureSuccessStatusCode();
    24. }
    25. _validatedUrl = url;
    26. }
    27. }

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

    1. protected override void OnModelCreating(ModelBuilder modelBuilder)
    2. {
    3. modelBuilder.Entity<Blog>()
    4. .Property<string>("Url")
    5. .HasField("_validatedUrl");
    6. }

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

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