網站首頁 編程語言 正文
我們現在已經知道如何使用Code First來定義簡單的領域類,并且如何使用DbContext類來執行數據庫操作?,F在我們來看下數據庫理論中的多樣性關系,我們會使用Code First來實現下面的幾種關系:
- 1、一對一關系: one to one
- 2、一對多關系: one to many
- 3、多對多關系::many to many
首先要明確關系的概念。關系就是定義兩個或多個對象之間是如何關聯的。它是由關系兩端的多樣性值識別的,比如,一對多意味著在關系的一端,只有一個實體,我們有時稱為父母;在關系的另一端,可能有多個實體,有時稱為孩子。EF API將那些端分別稱為主體和依賴。一對多關系也叫做一或零對多(One-or-Zero-to-Many),這意味著一個孩子可能有或可能沒有父母。一對一關系也稍微有些變化,就是關系的兩端都是可選的。
一、EF里的實體關系配置
Has方法
With方法
配置實體關系:
一對一表關系設計:
一對一關系并不常用,但是偶爾也會出現。如果一個實體有一些可選的數據,那么你可以選擇這種設計。
二、使用數據注解配置一對一關系
示例中Person表作為主表,IDCard表作為從表。
1、新建實體類
Person實體類結構如下:
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 配置一對一實體關系.Model { ////// 主表 /// [Table("Person")] public class Person { [Key] public int PersonId { get; set; } public string Name { get; set; } public int Sex { get; set; } public int Age { get; set; } ////// virtual 表示是導航屬性 啟用貪懶加載 /// [ForeignKey("PersonId")] public virtual IDCard IDCard { get; set; } } }
IDCard實體類結構如下:
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 配置一對一實體關系.Model { public class IDCard { [Key] public int PersonId { get; set; } public string IDCardNo { get; set; } public DateTime DataIssue { get; set; } public DateTime ValidTime { get; set; } public string IssuingAuthority { get; set; } ////// 導航屬性 /// public virtual Person Person { get; set; } } }
2、創建EF數據上下文類
using System; using System.Collections.Generic; using System.Data.Entity; using System.Linq; using System.Text; using System.Threading.Tasks; using 配置一對一實體關系.Model; namespace 配置一對一實體關系.EF { public class EFDbContext :DbContext { public EFDbContext() : base("name=CodeFirstApplication") { } public DbSetPersons { get; set; } public DbSet IDCards { get; set; } } }
3、使用數據遷移的方式創建數據庫
在使用數據遷移的過程中報錯:Unable to determine the principal end of an association between the types '配置一對一實體關系.Model.Person' and '配置一對一實體關系.Model.IDCard'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations。通過查找資料,解決辦法如下:添加Required數據注解,修改后的Person類結構如下:
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 配置一對一實體關系.Model { ////// 主表 /// [Table("Person")] public class Person { [Key] public int PersonId { get; set; } public string Name { get; set; } public int Sex { get; set; } public int Age { get; set; } ////// virtual 表示是導航屬性 啟用貪懶加載 /// [ForeignKey("PersonId")] [Required] public virtual IDCard IDCard { get; set; } } }
4、查看生成的數據庫表結構
通過查看數據庫表結構,發現Person表和IDCards表建立了主外鍵關系。
總結:使用數據注解配置一對一關系的步驟:
1、使用數據注解Key標識主鍵。
2、兩個實體之間的主鍵Key必須相同。
3、兩個實體之間有相互引用的導航屬性(使用virtual)。
4、在主表中設置外鍵關系[ForeignKey("PersonId")]。
三、使用Fluent API來配置一對一關系
1、創建A實體類結構如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 使用FluentAPI實現.Model { public class A { public int AId { get; set; } public string Name { get; set; } public virtual B B { get; set; } } }
2、創建B實體類結構如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 使用FluentAPI實現.Model { public class B { public int AId { get; set; } public string Name { get; set; } public virtual A A { get; set; } } }
3、使用Fluent API實現
using System; using System.Collections.Generic; using System.Data.Entity; using System.Linq; using System.Text; using System.Threading.Tasks; using 使用FluentAPI實現.Model; namespace 使用FluentAPI實現.EF { public class EFDbContext :DbContext { public EFDbContext() : base("name=CodeFirstApplication") { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity().ToTable("IDCard").HasKey(p => p.PersonId); modelBuilder.Entity ().ToTable("Person").HasKey(p => p.PersonId); #region 1.0 默認一對一配置 //modelBuilder.Entity ().HasRequired(p => p.IDCard).WithOptional(); #endregion #region 2.0 指定誰是主體對象誰是依賴對象 // 指定當前Person對象依賴IDCard對象,外鍵會創建到IDCard對象中,而IDCard對象是獨立存在的表,這種依賴關系配置是錯誤的。 //modelBuilder.Entity ().HasRequired(p => p.IDCard).WithRequiredDependent(t => t.Person); // 正確的依賴配置如下: //modelBuilder.Entity ().HasRequired(p => p.Person).WithRequiredDependent(t => t.IDCard); //modelBuilder.Entity().HasRequired(p => p.B).WithRequiredDependent(d=>d.A);//WithRequiredDependent A依賴對象(A依賴B,B可以對立存在,A會被建立外鍵) #endregion 指定誰是主要的對象 modelBuilder.Entity ().HasRequired(p => p.Person).WithRequiredPrincipal(t => t.IDCard); //WithRequiredPrincipal A 主體對象,執行A對象為被繼承者,也就是父級,B繼承A,A獨立存在 //modelBuilder.Entity().HasRequired(p => p.B).WithRequiredPrincipal(d => d.A); #region MyRegion #endregion base.OnModelCreating(modelBuilder); } } }
這里使用了HasKey方法,指定了一個表的主鍵,換言之,這是一個允許我們找到一個實體的獨一無二的值。之前我們沒有用這個方法是因為我們要么用了Key特性或者遵守了EF的默認約定(如果屬性名是由類名加上"Id"后綴或者只是"Id"組成,那么EF會計算出該主鍵)。因為我們現在使用了PersonId作為主鍵,所以我們現在需要給運行時提供額外的提示,這就是HasKey派生用場的地方。最后子表中的主鍵會成為父表中的外鍵。
因為該關系是可選的,所以它也稱為一或零對一(One-or-Zero-to-One)。關系的兩端都是必須要存在的關系稱為一對一。比如,每個人必須要有一個單獨的login,這是強制性的。你也可以使用WithRequiredDepentent或者WithRequiredPrincipal方法來代替WithOptional方法。
注意:我們可以總是從該關系的主體端或者依賴端來配置關系。我們總是需要配置一對一關系的兩端(即兩個實體),使用Has和With方法確保一對一關系的創建。
原文鏈接:https://www.cnblogs.com/dotnet261010/p/7955830.html
相關推薦
- 2022-05-06 Python?ORM框架之SQLAlchemy?的基礎用法_python
- 2022-06-30 go-micro集成RabbitMQ實戰和原理詳解_Golang
- 2022-08-25 Redis的4種緩存模式分享_Redis
- 2022-11-10 使用python的pandas讀取excel文件中的數據詳情_python
- 2022-04-03 Go語言讀取txt文檔的操作方法_Golang
- 2022-03-22 C語言字符串函數入門_C 語言
- 2022-04-17 算法時間復雜度和空間復雜度
- 2022-08-31 C語言數據結構之單鏈表與雙鏈表的增刪改查操作實現_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支