运维开发网

实体框架管理一对一的实体关系

运维开发网 https://www.qedev.com 2022-09-11 16:38 出处:网络
<本文详细讲解了Entity?Framework管理一对一实体关系的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下


<本文详细讲解了Entity?Framework管理一对一实体关系的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

现在我们知道了如何首先使用代码来定义一个简单的域类,以及如何使用DbContext类来执行数据库操作。现在我们来看看数据库理论中的多样性关系。我们将首先使用代码来实现以下关系:

1、一对一关系: one to one2、一对多关系: one to many3、多对多关系::many to many

首先,定义关系的概念。关系是两个或多个对象如何相关的定义。它由关系两端的差异值来标识。比如一对多,是指在关系的一端,只有一个实体,我们有时称之为父母;在关系的另一端,可能有多个实体,有时称为子实体。Ef将这些端点分别称为主体和依赖。一对多关系也称为一或零对多,这意味着一个孩子可能有也可能没有父母。一对一关系也略有变化,即关系的两端都是可选的。


一、EF里的实体关系配置

有方法


方法与


配置实体关系:


表关系设计:


一对一的关系不常用,但偶尔会发生。如果一个实体有一些可选的数据,那么你可以选择这个设计。

二、使用数据注解配置一对一关系

在这个例子中,Person表是主表,IDCard表是从表。

1、新建实体类

人实体类结构如下:

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{ /// lt;summarygt; /// 主表 /// lt;/summarygt; [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; } /// lt;summarygt; /// Virtual 表示是导航属性 启用贪懒加载 /// lt;/summarygt; [ForeignKey("PersonId")] public Virtual IDCard IDCard { get; set; } }}

ID实体的类结构如下:

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; } /// lt;summarygt; /// 导航属性 /// lt;/summarygt; 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 DbSetlt;Persongt; Persons { get; set; } public DbSetlt;IDCardgt; IDCards { get; set; } }}3、使用数据迁移的方式创建数据库

数据迁移期间报告的错误:无法确定类型之间关联的主体端# 39;配置一对一实体关系。模型。人物# 39;和# 39;配置一对一实体关系。模型。id卡# 39;。此关联得主体端必须使用关系流畅API或数据注释显式配置.通过查找数据,解决方法如下:添加需要的数据标注,修改后的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{ /// lt;summarygt; /// 主表 /// lt;/summarygt; [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; } /// lt;summarygt; /// Virtual 表示是导航属性 启用贪懒加载 /// lt;/summarygt; [ForeignKey("PersonId")] [Required] public Virtual IDCard IDCard { get; set; } }}4、查看生成的数据库表结构


通过查看数据库表结构,发现Person表和IDCards表已经建立了主键-外键关系。

摘要:使用数据注释配置一对一关系的步骤:

1.使用数据注释键来标识主键。
2。两个实体之间的主键必须相同。
3。两个实体之间有相互引用的导航属性(使用虚拟)。
4。设置主表[foreign key(quot;PersonIdquot)]。

三、使用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.Entitylt;IDCardgt;().ToTable("IDCard").HasKey(p =gt; p.PersonId); modelBuilder.Entitylt;Persongt;().ToTable("Person").HasKey(p =gt; p.PersonId); #region 1.0 默认一对一配置 //modelBuilder.Entitylt;Persongt;().HasRequired(p =gt; p.IDCard).WithOptional(); #endregion #region 2.0 指定谁是主体对象谁是依赖对象 // 指定当前Person对象依赖IDCard对象,外键会创建到IDCard对象中,而IDCard对象是独立存在的表,这种依赖关系配置是错误的。 //modelBuilder.Entitylt;Persongt;().HasRequired(p =gt; p.IDCard).WithRequiredDependent(t =gt; t.Person); // 正确的依赖配置如下: //modelBuilder.Entitylt;IDCardgt;().HasRequired(p =gt; p.Person).WithRequiredDependent(t =gt; t.IDCard); //modelBuilder.Entitylt;Agt;().HasRequired(p =gt; p.B).WithRequiredDependent(d=gt;d.A);//WithRequiredDependent A依赖对象(A依赖B,B可以对立存在,A会被建立外键) #endregion 指定谁是主要的对象 modelBuilder.Entitylt;IDCardgt;().HasRequired(p =gt; p.Person).WithRequiredPrincipal(t =gt; t.IDCard); //WithRequiredPrincipal A 主体对象,执行A对象为被继承者,也就是父级,B继承A,A独立存在 //modelBuilder.Entitylt;Agt;().HasRequired(p =gt; p.B).WithRequiredPrincipal(d =gt; d.A); #region MyRegion #endregion base.OnModelCreating(modelBuilder); } }}

这里,HasKey方法用于指定表的主键。换句话说,它是一个唯一的值,允许我们找到一个实体。我们以前没有使用这个方法,因为我们要么使用了Key特性,要么遵循了EF的默认约定(如果属性名是类名加quotIdquot或者后缀只是quotIdquot作文,那么EF会计算主键)。由于我们现在使用PersonId作为主键,我们现在需要为运行时提供额外的提示,这就是HasKey派上用场的地方。最后,子表中的主键成为父表中的外键。

因为这种关系是可选的,所以也称为一对一关系。关系的两端都是必须的。这种关系叫做一对一。例如,每个人必须有一个单独的登录,这是强制性的。也可以使用WithRequiredDepentent或WithRequiredPrincipal方法来代替WithOptional方法。

注意:我们总是可以从关系的主体端或从属端配置关系。我们总是需要配置一对一关系的两端(即两个实体),并使用Has和With方法来确保一对一关系的创建。

这就是本文关于实体框架管理一对一实体关系的全部内容。希望对大家的学习有所帮助/p>

0

精彩评论

暂无评论...
验证码 换一张
取 消