一. 隱藏屬性概述
隱藏屬性也叫影子屬性,該屬性不是在.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表數據
下面講第二個功能,隱藏屬性通常用于外鍵屬性。當二個實體存在主從關系,但在依賴實體類中找不到外鍵屬性時,默認是通過"約定"來創建隱藏外鍵屬性的。隱藏外鍵屬性將被命名為<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