一. 隱藏屬性概述 隱藏屬性也叫影子屬性,該屬性不是在.net實體類中定義的屬性,而是在EFCore模型中為該實體類型定義的屬性。這些屬性的值和狀態完全在變更跟蹤器中維護。它有二個功能:(1)當資料庫中某些欄位不想映射到實體類上公開的屬性時,隱藏屬性非常有用。(2)隱藏屬性通常是用於外鍵屬性,其中兩 ...
一. 隱藏屬性概述
隱藏屬性也叫影子屬性,該屬性不是在.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 隱藏屬性