Code First約定-Fluent API配置

来源:http://www.cnblogs.com/weekendLuang/archive/2017/04/16/6719716.html
-Advertisement-
Play Games

轉自:http://blog.163.com/m13864039250_1/blog/static/2138652482015283397609/ 用Fluent API 配置/映射屬性和類型 簡介 通常通過重寫派生DbContext 上的OnModelCreating 方法來訪問Code Firs ...


轉自:http://blog.163.com/m13864039250_1/blog/static/2138652482015283397609/

 

 

用Fluent API 配置/映射屬性和類型

簡介

通常通過重寫派生DbContext 上的OnModelCreating 方法來訪問Code First Fluent API。以下示例旨在顯示如何使用 Fluent API 執行各種任務,您可以將代碼複製出來併進行自定義,使之適用於您的模型。

屬性映射

Property 方法用於為每個屬於實體或複雜類型的屬性配置特性。Property 方法用於獲取給定屬性的配置對象。配置對象上的選項特定於要配置的類型;例如,IsUnicode 只能用於字元串屬性。

配置主鍵

要顯式將某個屬性設置為主鍵,可使用 HasKey 方法。在以下示例中,使用了 HasKey 方法對 OfficeAssignment 類型配置 InstructorID 主鍵。

modelBuilder.Entity<OfficeAssignment>().HasKey(t =>t.InstructorID);

 

配置組合主鍵

以下示例配置要作為Department 類型的組合主鍵的DepartmentID 和 Name 屬性。

modelBuilder.Entity<Department>().HasKey(t => new { t.DepartmentID, t.Name });

 

關閉數值主鍵的標識

以下示例將DepartmentID 屬性設置為System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.None,以指示該值不由資料庫生成。

modelBuilder.Entity<Department>().Property(t =>t.DepartmentID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

 

指定屬性的最大長度

在以下示例中,Name屬性不應超過 50 個字元。如果其值超過 50 個字元,則出現 DbEntityValidationException 異常。如果 Code First 基於此模型創建資料庫,它還會將 Name 列的最大長度設置為50 個字元。

modelBuilder.Entity<Department>().Property(t =>t.Name).HasMaxLength(50);

 

將屬性配置為必需

在下麵的示例中,Name屬性是必需的。如果不指定 Name,則出現 DbEntityValidationException 異常。如果 Code First 基於此模型創建資料庫,則用於存儲此屬性的列將不可為空。

modelBuilder.Entity<Department>().Property(t =>t.Name).IsRequired();

 

指定不將CLR 屬性映射到資料庫中的列

以下示例顯示如何指定CLR 類型的屬性不映射到資料庫中的列。

modelBuilder.Entity<Department>().Ignore(t => t.Budget);

 

將CLR 屬性映射到資料庫中的特定列

以下示例將Name CLR 屬性映射到DepartmentName 資料庫列。

modelBuilder.Entity<Department>().Property(t =>t.Name).HasColumnName("DepartmentName");

 

重命名模型中未定義的外鍵

如果您選擇不對CLR 類型定義外鍵,但希望指定它在資料庫中應使用的名稱,請編碼如下:

modelBuilder.Entity<Course>()

        .HasRequired(c => c.Department)

        .WithMany(t => t.Courses)

        .Map(m => m.MapKey("ChangedDepartmentID"));

 

配置字元串屬性是否支持Unicode 內容

預設情況下,字元串為Unicode(SQLServer 中的nvarchar)。您可以使用IsUnicode 方法指定字元串應為varchar 類型。

modelBuilder.Entity<Department>()

        .Property(t => t.Name)

        .IsUnicode(false);

 

配置資料庫列的數據類型

HasColumnType 方法支持映射到相同基本類型的不同表示。使用此方法並不支持在運行時執行任何數據轉換。請註意,IsUnicode 是將列設置為 varchar 的首選方法,因為它與資料庫無關。

modelBuilder.Entity<Department>()

        .Property(p => p.Name)

        .HasColumnType("varchar");

 

配置複雜類型的屬性

對複雜類型配置標量屬性有兩種方法。

可以對ComplexTypeConfiguration 調用Property。

modelBuilder.ComplexType<Details>()

        .Property(t => t.Location)

        .HasMaxLength(20);

 

也可以使用點表示法訪問複雜類型的屬性。

modelBuilder.Entity<OnsiteCourse>()

        .Property(t => t.Details.Location)

        .HasMaxLength(20);

 

將屬性配置為用作樂觀併發令牌

要指定實體中的某個屬性表示併發令牌,可使用 ConcurrencyCheck 特性或 IsConcurrencyToken 方法。

modelBuilder.Entity<OfficeAssignment>()

        .Property(t => t.Timestamp)

        .IsConcurrencyToken();

 

也可以使用IsRowVersion 方法將屬性配置為資料庫中的行版本。將屬性設置為行版本會自動將它配置為樂觀併發令牌。

modelBuilder.Entity<OfficeAssignment>()

        .Property(t => t.Timestamp)

        .IsRowVersion();

 

類型映射

將類指定為複雜類型

按約定,沒有指定主鍵的類型將被視為複雜類型。在一些情況下,Code First 不會檢測複雜類型(例如,如果您有名為“ID”的屬性,但不想將它用作主鍵)。在此類情況下,您將使用 Fluent API 顯式指定某類型是複雜類型。

modelBuilder.ComplexType<Details>();

 

指定不將CLR 實體類型映射到資料庫中的表

以下示例顯示如何排除一個 CLR 類型,使之不映射到資料庫中的表。

modelBuilder.Ignore<OnlineCourse>();

 

將CLR 實體類型映射到資料庫中的特定表

Department 的所有屬性都將映射到名為 t_ Department 的表中的列。

modelBuilder.Entity<Department>().ToTable("t_Department");

 

您也可以這樣指定架構名稱:

modelBuilder.Entity<Department>().ToTable("t_Department", "school");

 

映射“每個層次結構一張表(TPH)”繼承

在 TPH 映射情形下,繼承層次結構中的所有類型都將映射到同一個表。鑒別器列用於標識每行的類型。使用 Code First 創建模型時,TPH 參與繼承層次結構的類型所用的預設策略。預設情況下,鑒別器列將添加到名為“Discriminator”的表,且層次結構中每個類型的 CLR 類型名稱都將用作鑒別器值。可以使用 Fluent API 修改預設行為。

modelBuilder.Entity<Course>()

        .Map<Course>(m=> m.Requires("Type").HasValue("Course"))

        .Map<OnsiteCourse>(m=> m.Requires("Type").HasValue("OnsiteCourse"));

 

映射“每個類型一張表(TPT)”繼承

在 TPT 映射情形下,所有類型分別映射到不同的表。僅屬於某個基類型或派生類型的屬性存儲在映射到該類型的一個表中。映射到派生類型的表還會存儲一個將派生表與基表聯接的外鍵。

modelBuilder.Entity<Course>().ToTable("Course");

modelBuilder.Entity<OnsiteCourse>().ToTable("OnsiteCourse");

 

映射“每個具體類一張表(TPC)”繼承

在 TPC 映射情形下,層次結構中的所有非抽象類型分別映射到不同的表。映射到派生類的表與映射到資料庫中基類的表並無關係。類的所有屬性(包括繼承屬性)都將映射到相應表的列。

調用MapInheritedProperties 方法來配置每個派生類型。MapInheritedProperties 將繼承自基類的所有屬性重新映射到派生類的表中的新列。

註意:因為屬於TPC 繼承層次結構的表並不使用同一個主鍵,因此,如果您讓資料庫生成的值具有相同標識種子,則在映射到子類的表中執行插入操作時,會產生重覆的實體鍵。要解決此問題,可以為每個表指定不同的初始種子值,或關閉主鍵屬性的標識。當使用 Code First 時,標識就是整數鍵屬性的預設值。

modelBuilder.Entity<Course>()

  .Property(c => c.CourseID)

  .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

 

modelBuilder.Entity<OnsiteCourse>().Map(m =>

{

  m.MapInheritedProperties();

  m.ToTable("OnsiteCourse");

});

 

modelBuilder.Entity<OnlineCourse>().Map(m =>

{

  m.MapInheritedProperties();

  m.ToTable("OnlineCourse");

});

 

將實體類型的CLR 屬性映射到資料庫中的多個表(實體拆分)

實體拆分允許一個實體類型的屬性分散在多個表中。在以下示例中,Department 實體拆分到兩個表中:Department 和DepartmentDetails。實體拆分通過多次調用 Map 方法將一部分屬性映射到特定表。

modelBuilder.Entity<Department>()

.Map(m=>

{

  m.Properties(t => new{ t.DepartmentID, t.Name });

  m.ToTable("Department");

})

.Map(m=>

{

  m.Properties(t=> new { t.DepartmentID, t.Administrator,t.StartDate, t.Budget });

  m.ToTable("DepartmentDetails");

 });

 

將多個實體類型映射到資料庫中的一個表(表拆分)

以下示例將使用同一個主鍵的兩個實體類型映射到同一個表。

modelBuilder.Entity<OfficeAssignment>()

  .HasKey(t => t.InstructorID);

modelBuilder.Entity<Instructor>()

    .HasRequired(t => t.OfficeAssignment)

    .WithRequiredPrincipal(t =>t.Instructor);

modelBuilder.Entity<Instructor>().ToTable("Instructor");

modelBuilder.Entity<OfficeAssignment>().ToTable("Instructor");

 

使用FluentAPI配置關係

簡介

使用FluentAPI配置關係的時候,首先要獲得一個EntityTypeConfiguration實例,然後使用其上的HasRequired, HasOptional或者 HasMany方法來指定當前實體參與的關係類型。HasRequired 和HasOptional方法需要一個lambda表達式來指定一個導航屬性,HasMany方法需要一個lambda表達式指定一個集合導航屬性。然後可以使用WithRequired, WithOptional和WithMany方法來指定反嚮導航屬性,這些方法有不帶參數的重載用來指定單嚮導航。

之後還可以使用HasForeignKey方法來指定外鍵屬性。

配置【必須-可選】關係(1-0..1)

OfficeAssignment的鍵屬性不符合命名約定,所以需要我們顯式指定。下麵的關係表明,OfficeAssignment的Instructor必須存在,但是Instructor的OfficeAssignment不是必須存在的。

modelBuilder.Entity<OfficeAssignment>()

  .HasKey(t => t.InstructorID);

 

// Map one-to-zero or one relationship

modelBuilder.Entity<OfficeAssignment>()

  .HasRequired(t => t.Instructor)

  .WithOptional(t => t.OfficeAssignment);

配置兩端都是必須的關係(1-1)

大多數情況下,EF都能推斷哪一個類型是依賴項或者是主體項。然而當關係的兩端都是必須的或者都是可選的,那麼EF就不能識別依賴項或者是主體項。如果關係兩端都是必須的,那麼在HasRequired方法後使用WithRequiredPrincipal或者WithRequiredDependent來確定主體。如果關係兩端都是可選的,那麼在HasRequired方法後使用WithOptionalPrincipal和WithOptionalDependent。

 

modelBuilder.Entity<OfficeAssignment>()

  .HasKey(t => t.InstructorID);

 

modelBuilder.Entity<Instructor>()

  .HasRequired(t => t.OfficeAssignment)

  .WithRequiredPrincipal(t => t.Instructor);

 

配置多對多關係

下麵的代碼配置了一個多對多關係,CodeFirst會使用命名約定來創建連接表,命名約定會使用Course_CourseID 和 Instructor_InstructorID作為連接表的列。

 

modelBuilder.Entity<Course>()

        .HasMany(t => t.Instructors)

        .WithMany(t => t.Courses);

如果想指定連接表的表名和列名,需要使用Map方法,如下:

modelBuilder.Entity<Course>()

        .HasMany(t => t.Instructors)

        .WithMany(t => t.Courses)

        .Map(m =>

        {

          m.ToTable("CourseInstructor");

          m.MapLeftKey("CourseID");

          m.MapRightKey("InstructorID");

        });

 

配置單嚮導航屬

所謂單嚮導航屬性指的是只在關係的一端定義了導航屬性。按照約定,CodeFirst將單嚮導航理解為一對多關係,如果需要一對一的單嚮導航屬性,需要使用如下方法:

modelBuilder.Entity<OfficeAssignment>()

  .HasKey(t => t.InstructorID);

 

modelBuilder.Entity<Instructor>()

  .HasRequired(t => t.OfficeAssignment)

  .WithRequiredPrincipal();

 

啟用級聯刪除

使用WillCascadeOnDelete方法來配置關係是否允許級聯刪除。如果外鍵是不可空的,CodeFirst預設會設置級聯刪除;否則,不會設置級聯刪除,當主體被刪除後,外鍵將會被置空。

可以使用如下代碼移除此約定:

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();

下麵的代碼片段配置為外鍵不能為空,而且禁用了級聯刪除。

 

modelBuilder.Entity<Course>()

  .HasRequired(t => t.Department)

  .WithMany(t => t.Courses)

  .HasForeignKey(d => d.DepartmentID)

  .WillCascadeOnDelete(false);

配置組合外鍵

下麵的代碼配置了組合外鍵

modelBuilder.Entity<Department>()

  .HasKey(d => new{ d.DepartmentID, d.Name });

 

// Composite foreign key

modelBuilder.Entity<Course>()

    .HasRequired(c => c.Department)

    .WithMany(d => d.Courses)

    .HasForeignKey(d => new { d.DepartmentID, d.DepartmentName });

 

配置不符合命名約定的外鍵屬性

SomeDepartmentID屬性不符合外鍵命名約定,需要使用如下方法將其設置為外鍵屬性:

modelBuilder.Entity<Course>()

         .HasRequired(c => c.Department)

         .WithMany(d => d.Courses)

         .HasForeignKey(c =>c.SomeDepartmentID);


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Mac下自帶的終端並不好用,當你打開終端的時候是一個白花花的視窗,其實Mac自帶幾種shell,預設使用的是bash,可以通過 查看幾種shell 其中最為強大的當然是zsh,相比起bash來,zsh可以自動補全命令行,可以更換多種主題,可以顯示Git倉庫的狀態等等,非常強大。但是早期因為zsh配置 ...
  • 1. 概述 <<深入理解Java虛擬機--JVM高級特性與最佳實踐>>第一章就談到自己編譯jdk,來吧。 2. 編譯環境 VMware12 CentOS-7-x86_64-Everything-1611 3. 軟體準備 Bootstrap JDK: jdk-7u79-linux-x64.tar.gz ...
  • linux shell 可以用戶定義函數,然後在shell腳本中可以隨便調用。下麵說說它的定義方法,以及調用需要註意那些事項。 原文和作者一起討論:http://www.cnblogs.com/intsmaze/p/6675421.html 微信:intsmaze 原文和作者一起討論:http:// ...
  • 1、教學環境 2、雲計算概念 3、工作崗位與內容 4、linux系統簡介 5、shell概念 6、linux基礎命令 man/help/info/pwd/cd/ls/mkdir/stat/touch/rm/copy/mv/echo/cat/less/more/tty/管道 7、重定向 >,1>,2> ...
  • 什麼是JSP JSP屬於動態網頁,例如當上網搜索信息,程式就進行了查詢資料庫的操作,這就是一個動態網頁所實現的功能。HTML不具備查詢資料庫的能力,java代碼卻可以通過JDBC技術訪問資料庫。因此,可在HTML代碼中間混合java代碼,讓網頁擁有訪問資料庫的功能。嵌入了java代碼的網頁,就是JS ...
  • 1.導出系統日誌,以當前日期命名 @echo offset nowDate=%date%set tmp=%nowDate:~0,-3%set file=%tmp:/=-%系統日誌.evtx echo %nowDate%>%file% wevtutil epl system >>%file% 2.we ...
  • 第三章 MVC 模式,項目和約定 在深入瞭解ASP.NET Core MVC的細節之前,我想確保您熟悉MVC設計模式背後的思路以及將其轉換為ASP.NET Core MVC項目的方式。 您可能已經瞭解本章中討論的一些想法和約定,特別是如果您已經完成了高級ASP.NET或C#開發。 如果沒有,我鼓勵你 ...
  • 從開始接觸.Net Core到現在已經有將近一年的時間了,今天來做一下相關的學習總結,順便也回憶一下自己這段時間以來的成長。 有一點不得不承認的是,在接觸.Net Core之前,我對於linux系統一點也不瞭解,也未曾有過主動去學習的念頭,在接觸了.Net Core之後才開始慢慢學習linux相關知 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...