在昨天的內容,我們建立了 Model 並為多個 Properties 設定了 Attribute,這種方式稱為 Data Annotations,這種方式在整體開發上速度快、整合度也高,比如說 Scaffolding 產生的 View 就直接包含了一些 Validation,Submit Form 時也會有後端驗證。
不過我個人認為 Data Annotations 在做 Table 的關聯時,稍嫌有點不直覺,如果可以直接看 Code 就知道 Table 之間的關聯的話,那就更好了!
所以今天要介紹的是另一種設定 Table 屬性的方式,EF Core Fluent API。
Fluent API 是 EF Core 為 Code First 開發方式提供的一種可設定 Model(e.g. Table 欄位), Entity(e.g. Table 的 PK, FK) 以及 Property(e.g. Default Value, Nullable 等) 的設計模式。
設計上運用 Lambda 表達式,所以 Code 不論是寫起來或看起來,我都覺得蠻像 Linq 的,畢竟 Linq 也是使用到了 Lambda,所以還蠻有親和力的(對我來說啦)。
以下換個方式來關聯 Events 和 EventsInfo 這兩個 Table。
Events:
EventsInfo:
接著執行 Migration,產生新的 Migration 檔:
可以看到這次 database update 的內容為移除 EventsInfo 對 Events 的 FK 以及索引、欄位,確定原本使用 Data Annotatition 是有建立關聯的,順便附上 SSMS 的圖片證明:
接下來就 update 到 DB,並再打開一次 SSMS 資料表圖表:
可以看到 EventsInfo 的 EventsId 以及與 Events 的關聯被移除了,接下來可以用 Fluent API 來實現關聯。
我們再將 Events 和 EventsInfo 取消註解,並且 EventsInfo 的 EventsId rename 為 EventsInfoOfEventsId:
此時如果我們執行 Migration,會出現請你去建立 Events 和 EventsInfo 的關聯與 FK:
同時也可以看到提示的最後一段,在 OnModelCreating
建立所需的關聯,而這個 Function 其實是需要寫在 DbContext 內,且我們需要以 override 的方式去建立此 Function:
可以看到使用 Lambda 讓整個 Code 可以直接顯示出 Entity 之間的關係:
modelBuilder.Entity<Events>()
=> 代表現在要設定 Events.HasOne<EventsInfo>(e => e.EventsInfo)
=> 表示 Events 與 EventsInfo 有關聯.WithOne(ei => ei.Events)
=> EventsInfo 與 Events 有關聯,與前一項一起表示為 1 對 1 的關係。 .HasForeignKey<EventsInfo>(ei => ei.EventsInfoOfEventsId);
=> 指定哪一個欄位是 FK,執行 Migration 後來看一下 Migration 的內容:
可以看到關聯與欄位、索引都加回來了,接著執行 database update:
從圖表可以看到關聯和欄位也確實被建立起來了。
今天的內容提供了另一個方式來設定關聯、欄位等,但 FluentAPI 與 Data Annotation 該怎麼選,我相信還是有各自適合它們的情境。
若一般使用上,我個人還是會選擇 Data Annotation,畢竟可以直接在 Model 上一路開發到底也蠻舒服的。
明天會介紹如何使用 Fluent API 來設定欄位長度、是否允許 Null 等較針對 Table 欄位屬性的部分,那麼明天見囉。
Fluent API in Entity Framework Core