阴影属性Shadow Properties

影子属性是未在 .NET 实体类中定义但在 EF Core 模型中为该实体类型定义的属性。 这些属性的值和状态纯粹在更改跟踪器中进行维护。 当数据库中的数据不应在映射的实体类型上公开时,阴影属性非常有用。

外键阴影属性Foreign key shadow properties

影子属性最常用于外键属性,其中两个实体之间的关系由数据库中的外键值表示,但使用实体之间的导航属性在实体类型上管理关系各种. 按照约定,当发现关系但在依赖实体类中找不到外键属性时,EF 会引入一个影子属性。

属性将命名为 <navigation property name><principal key property name> (指向主体实体的依赖实体上的导航用于命名)。 如果主体键属性名称包含导航属性的名称,则该名称将只 <principal key property name>。 如果依赖实体上没有导航属性,则会在其位置使用主体类型名称。

例如,下面的代码列表将导致向 Post 实体引入 BlogId 影子属性:

  1. class MyContext : DbContext
  2. {
  3. public DbSet<Blog> Blogs { get; set; }
  4. public DbSet<Post> Posts { get; set; }
  5. }
  6. public class Blog
  7. {
  8. public int BlogId { get; set; }
  9. public string Url { get; set; }
  10. public List<Post> Posts { get; set; }
  11. }
  12. public class Post
  13. {
  14. public int PostId { get; set; }
  15. public string Title { get; set; }
  16. public string Content { get; set; }
  17. // Since there is no CLR property which holds the foreign
  18. // key for this relationship, a shadow property is created.
  19. public Blog Blog { get; set; }
  20. }

配置阴影属性Configuring shadow properties

你可以使用 “熟知 API” 配置阴影属性。 在您调用了 Property的字符串重载后,您可以将对其他属性的任何配置调用链接在一起。 在下面的示例中,由于 Blog 没有名为 LastUpdated的 CLR 属性,因此将创建一个影子属性:

  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<DateTime>("LastUpdated");
  8. }
  9. }
  10. public class Blog
  11. {
  12. public int BlogId { get; set; }
  13. public string Url { get; set; }
  14. }

如果提供给 Property 方法的名称与现有属性(在实体类中定义)的名称相匹配,则代码将配置该现有属性,而不是引入新的阴影属性。

访问阴影属性Accessing shadow properties

可以通过 ChangeTracker API 获取和更改影子属性值:

  1. context.Entry(myBlog).Property("LastUpdated").CurrentValue = DateTime.Now;

可以通过 EF.Property 静态方法在 LINQ 查询中引用阴影属性:

  1. var blogs = context.Blogs
  2. .OrderBy(b => EF.Property<DateTime>(b, "LastUpdated"));