影子属性

影子属性是 EF Core 模型中在 .NET 实体类型之外定义的实体类型属性。这些属性的值和状态只在变更跟踪器(ChangeTracker)中维护。

影子属性的值可以通过 ChangeTracker API 来获取和变更。

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

影子属性也可以在 LINQ 查询中通过静态方法 EF.Property 来引用。

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

惯例

当存在一个关系,但其中的依赖实体类型不存在相应的外键属性时,相应的影子属性就会被惯例创建。这种情况下就引入了影子外键属性。影子外键属性将被命名为 <导航属性名><主键属性名>(使用依赖实体类型上指向主实体类型的导航属性来命名)。如果主键属性名本身包含导航属性名,则影子属性名只会是 <主键属性名>。如果依赖实体类型中没有定义相应的导航属性,则改用主类型名称。

例如,以下列出的代码将产生一个引入给 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. public Blog Blog { get; set; }
  18. }

数据注解

影子属性无法通过数据注解来创建。

流式 API

可以使用流式 API 来配置影子属性。在你调用了 Property 方法的字符串参数重载后,你可以通过链式调用对任何其他属性进行配置。

如果提供给 Property 方法的名称与现有属性的名称(影子属性名称或实体类型上定义的属性名称)匹配,那么代码配置的就是现有属性,而不是引入新的影子属性。

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