支持字段

支持字段允许 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"));