歡迎光臨
每天分享高質量文章

“幕後英雄”之Backing Fields【Microsoft Entity Framework Core隨筆】

劉德華 有一首歌叫《馬桶》,其中有一句歌詞是:每一個馬桶都是英雄。
EFCore也有一個英雄,在幕後默默地任勞任怨。它就叫 “支援欄位” (Backing Fields):

  • 中文版:https://docs.microsoft.com/zh-cn/ef/core/modeling/backing-field
    支援欄位允許 EF 讀取和/或寫入欄位而不是一個屬性。 在類中的封裝用於限制的使用和/或增強圍繞訪問資料的語意由應用程式程式碼,但值應進行讀取和/或寫入到資料庫而無需使用這些限制時這很有用 /增強功能。
  • 英文版:https://docs.microsoft.com/en-us/ef/core/modeling/backing-field
    Backing fields allow EF to read and/or write to a field rather than a property. This can be useful when encapsulation in the class is being used to restrict the use of and/or enhance the semantics around access to the data by application code, but the value should be read from and/or written to the database without using those restrictions/enhancements.

它可以用於什麼場景呢?簡單地說,當我們沒有特別地指定類的屬性與資料表欄位名的話,在裝載 資料表的內容 到 類 的時候,EFCore會直接地找到屬性名對應的資料表欄位名,然後把欄位的內容賦值到類屬性中(留意,我說的是 類 的 屬性 Property,而不是 欄位 Field)。但是萬一我們不想EFCore這樣做呢?例如,以下的倆場景:
– 場景一
我們有一個User類,它有一個叫Password的屬性,由於是單向加密,所以希望:每次對它賦值的時候,它都自動做MD5加密;然後對它讀取的時候,它都只傳回MD5加密後的內容(而不是加密前的內容)
– 場景二
某些金融應用,由於需要支援不同貨幣品種的小數點後位數精度的要求,金額在資料庫儲存的時候,或者和內部其他系統做資料交換的時候(通常極有可能是近似於整表匯出了),都是整型。然後只有在人機對話的介面,才把進行小數點運算後的結果顯示出來。至於貨幣品種,除了世界各國的貨幣,還可能會有虛擬貨幣(你懂得),所以小數點後位數的需求都不一樣的啊。

(本篇的例子的程式,可以從 https://github.com/kentliu2007/EFCoreDemo/tree/master/BackingField 下載,建議可以下載後對照著程式碼來閱讀本篇。我用的是 VS2017)

按照上述場景的需求,我們有:

  • 資料表:
    • Clients 的索引

    • ClientAccountBalance 的索引
    • Currencies 的索引

    • Users


    • Clients, ClientAccountBalance, Currencies
  • 測試資料:
  • EF6的實現方式
    讓我們先來看看如果用EF6怎麼做?EF6的話,有設計器啊,輕鬆容易,毫無壓力:

    • 專案:
    • EF Model Diagram:
    • ClientAccountBalance的設定:

      rawAmount的設定,setter和getter都是internal的,因為這個是非 對外(public)屬性
    • User的設定:

      rawPassword的設定,setter和getter都是internal的,因為這個是非 對外(public)屬性
    • 針對場景一的,在Custom目錄下,User類的程式碼:
    • 針對場景二的,在Custom目錄下,ClientAccountBalance類的程式碼:

大功告成,簡單吧?

  • EFCore的實現方式
    EFCore沒有設計器,難道就“臣妾做不到”了嗎?其實,藉助Backing Fields的話,用EFCore來實現,更簡單,更優雅。

    • 告訴EFCore,指定 類 的 某個Property,所對照的 類 的 Field 是哪個,且還可以指定它所對照的資料表的欄位名:
    • 告訴EFCore,類 的 某個Field ,它所對照的資料表的欄位名:
    • Backing Fields兩個主要用法:
      在 DbContext.OnModelCreating方法裡面,

      modelBuilder.Entity().Property(b => b.MyProperty).HasField("_myField").HasColumnName("ColumnName");
      modelBuilder.Entity().Property("_myField").HasColumnName("ColumnName");
    • 專案:
    • DbContext的程式(Backing Fields出沒,請註意):
    • 針對場景一的,User的程式:
    • 針對場景二的,ClientAccountBalance的程式:

搞定了。單刀直入,簡單利索。對吧?
真的就可以嗎?好吧,如果不信的話,可以下載程式碼,跑一下 單元測試 來體驗一下嘛 😛 。

在幕後英雄Backing Fields的幫助下,我們輕輕鬆松地用幾行程式碼就搞定了上述兩個情景的慄子了(重點在 DbContext 程式裡面啊)。很棒,對吧?

下一篇,我將會分享一下,怎樣在 EFCore上,藉助它的 Lazy Loading 來實現,在 EF5/6 上面輕鬆地用 Table Mapping就實現了的 Entity Split 功能。
明年(今天是年二九嘛)見 😀

相關文章:

原文地址:https://www.cnblogs.com/fatkent/p/10348864.html

贊(0)

分享創造快樂