支持字段Backing Fields

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

基本配置Basic configuration

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

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

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

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

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

你还可以使用数据批注(在 EFCore 5.0 中提供)或流畅的 API (例如,如果该字段名称与上述约定不对应)来配置支持字段:

  1. public class Blog
  2. {
  3. private string _validatedUrl;
  4. public int BlogId { get; set; }
  5. [BackingField(nameof(_validatedUrl))]
  6. public string Url
  7. {
  8. get { return _validatedUrl; }
  9. }
  10. public void SetUrl(string url)
  11. {
  12. // put your validation code here
  13. _validatedUrl = url;
  14. }
  15. }
  1. protected override void OnModelCreating(ModelBuilder modelBuilder)
  2. {
  3. modelBuilder.Entity<Blog>()
  4. .Property(b => b.Url)
  5. .HasField("_validatedUrl");
  6. }

字段和属性访问Field and property access

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

  1. protected override void OnModelCreating(ModelBuilder modelBuilder)
  2. {
  3. modelBuilder.Entity<Blog>()
  4. .Property(b => b.Url)
  5. .HasField("_validatedUrl")
  6. .UsePropertyAccessMode(PropertyAccessMode.PreferFieldDuringConstruction);
  7. }

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

备注

使用 EF Core 3.0,默认属性访问模式从PreferFieldDuringConstruction更改为。 PreferField

仅限字段的属性Field-only properties

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

可以通过在Property(...) 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("_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. }

EF 将尝试查找具有给定名称的 CLR 属性,如果找不到属性,则尝试查找一个字段。 如果属性和字段均未找到,则将改为设置影子属性。

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

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