一. 隱藏屬性概述
隱藏屬性也叫影子屬性,該屬性不是在.net實(shí)體類中定義的屬性,而是在EFCore模型中為該實(shí)體類型定義的屬性。這些屬性的值和狀態(tài)完全在變更跟蹤器中維護(hù)。它有二個(gè)功能:(1)當(dāng)數(shù)據(jù)庫(kù)中某些字段不想映射到實(shí)體類上公開的屬性時(shí),隱藏屬性非常有用。(2)隱藏屬性通常是用于外鍵屬性,其中兩個(gè)實(shí)體之間的關(guān)系由數(shù)據(jù)庫(kù)中的外鍵值表示,但是兩個(gè)實(shí)體關(guān)系是使用實(shí)體類型之間的導(dǎo)航屬性進(jìn)行管理(這個(gè)在下面約定中講到)。
隱藏屬性值可以通過ChangeTracker API獲取和更改:
context.Entry(myBlog).Property("LastUpdated").CurrentValue = DateTime.Now;
下面講第一個(gè)功能:當(dāng)數(shù)據(jù)庫(kù)中某些字段不想映射到實(shí)體類上公開的屬性時(shí),隱藏屬性非常有用
1.1 配置隱藏屬性
不能通過數(shù)據(jù)注釋來創(chuàng)建隱藏屬性,只能通過 Fluent API 來創(chuàng)建, Blog實(shí)體中沒有映射LastUpdated公開屬性,但創(chuàng)建了隱藏屬性。
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 設(shè)置隱藏屬性值
在新增時(shí)blog一條數(shù)據(jù)時(shí),通過ChangeTracker API可以為隱藏屬性LastUpdated設(shè)置時(shí)間值,提交到數(shù)據(jù)庫(kù)表中。
[HttpPost]
public async Task<IActionResult> Create([Bind("Url")] Blog blog)
{
if (ModelState.IsValid)
{
//設(shè)置隱藏屬性的值
BloggingContext.Entry(blog).Property("LastUpdated").CurrentValue = DateTime.Now;
BloggingContext.Add<Blog>(blog);
await BloggingContext.SaveChangesAsync();
}
return View();
}
1.3 讀取blog表數(shù)據(jù)
下面講第二個(gè)功能,隱藏屬性通常用于外鍵屬性。當(dāng)二個(gè)實(shí)體存在主從關(guān)系,但在依賴實(shí)體類中找不到外鍵屬性時(shí),默認(rèn)是通過"約定"來創(chuàng)建隱藏外鍵屬性的。隱藏外鍵屬性將被命名為<navigation property name><principal key property name>。以下面的示例來說:post依賴實(shí)體中包含了隱藏的外鍵屬性 “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; }
}
下面簡(jiǎn)單測(cè)試下,通過初例化一個(gè)的Post依賴實(shí)體,查看該實(shí)例中是否包含了BlogId 外鍵隱藏屬性,通過ChangeTracker API來獲取,使用斷點(diǎn)查看該BlogId 隱藏屬性確實(shí)存在,只是在Post實(shí)體上是非公開的外鍵屬性:
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