一. 隐藏属性概述
隐藏属性也叫影子属性, 该属性不是在. net 实体类中定义的属性, 而是在 EFCore 模型中为该实体类型定义的属性. 这些属性的值和状态完全在变更跟踪器中维护. 它有二个功能:(1) 当数据库中某些字段不想映射到实体类上公开的属性时, 隐藏属性非常有用.(2) 隐藏属性通常是用于外键属性, 其中两个实体之间的关系由数据库中的外键值表示, 但是两个实体关系是使用实体类型之间的导航属性进行管理 (这个在下面约定中讲到).
隐藏属性值可以通过 ChangeTracker API 获取和更改:
context.Entry(myBlog).Property("LastUpdated").CurrentValue = DateTime.Now;
下面讲第一个功能: 当数据库中某些字段不想映射到实体类上公开的属性时, 隐藏属性非常有用
1.1 配置隐藏属性
不能通过数据注释来创建隐藏属性, 只能通过 Fluent API 来创建, Blog 实体中没有映射 LastUpdated 公开属性, 但创建了隐藏属性.
- class BloggingContext: DbContext
- {
- public DbSet<Blog> Blogs { get; set; }
- protected override void OnModelCreating(ModelBuilder modelBuilder)
- {
- modelBuilder.Entity<Blog>().Property<DateTime>("LastUpdated");
- }
- }
- public class Blog
- {
- public int BlogId { get; set; }
- public string Url { get; set; }
- }
1.2 设置隐藏属性值
在新增时 blog 一条数据时, 通过 ChangeTracker API 可以为隐藏属性 LastUpdated 设置时间值, 提交到数据库表中.
- [HttpPost]
- public async Task<IActionResult> Create([Bind("Url")] Blog blog)
- {
- if (ModelState.IsValid)
- {
- // 设置隐藏属性的值
- BloggingContext.Entry(blog).Property("LastUpdated").CurrentValue = DateTime.Now;
- BloggingContext.Add<Blog>(blog);
- await BloggingContext.SaveChangesAsync();
- }
- return View();
- }
1.3 读取 blog 表数据
可以通过 LINQ 查询中引用隐藏属性 EF.Property 静态方法, 通过隐藏属性 LastUpdated 排序, 读取 blog 集合数据.
var blogs = context.Blogs.OrderBy(b => EF.Property<DateTime>(b, "LastUpdated"));
二. 约定
下面讲第二个功能, 隐藏属性通常用于外键属性. 当二个实体存在主从关系, 但在依赖实体类中找不到外键属性时, 默认是通过 "约定" 来创建隐藏外键属性的. 隐藏外键属性将被命名为 < navigation property name><principal key property name>. 以下面的示例来说: post 依赖实体中包含了隐藏的外键属性 "BlogId".
- public class Blog
- {
- public int BlogId { get; set; }
- public string Url { get; set; }
- public List<Post> Posts { get; set; }
- }
- public class Post
- {
- public int PostId { get; set; }
- public string Title { get; set; }
- public string Content { get; set; }
- public Blog Blog { get; set; }
- }
下面简单测试下, 通过初例化一个的 Post 依赖实体, 查看该实例中是否包含了 BlogId 外键隐藏属性, 通过 ChangeTracker API 来获取, 使用断点查看该 BlogId 隐藏属性确实存在, 只是在 Post 实体上是非公开的外键属性:
- public void OnGet()
- {
- object obj = _bloggingContext.Entry(new Post()).Property("BlogId").CurrentValue;
- }
- _bloggingContext.Entry(new Post()).Property("BlogId")
- {Microsoft.EntityFrameworkCore.ChangeTracking.PropertyEntry}
- CurrentValue: null
- EntityEntry: {Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalMixedEntityEntry}
- InternalEntry: {Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalMixedEntityEntry}
- IsModified: false
- IsTemporary: false
- Metadata (Microsoft.EntityFrameworkCore.ChangeTracking.MemberEntry): {Property: Post.BlogId (no field, Nullable<int>) Shadow FK Index 1 1 1 0 1}
- Metadata: {Property: Post.BlogId (no field, Nullable<int>) Shadow FK Index 1 1 1 0 1}
- OriginalValue: null
参考文献:
官方文档: EF 隐藏属性
来源: http://www.bubuko.com/infodetail-2957565.html