文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Entity Framework如何管理一对一实体关系

2023-06-29 09:52

关注

这篇文章给大家分享的是有关Entity Framework如何管理一对一实体关系的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

我们现在已经知道如何使用Code First来定义简单的领域类,并且如何使用DbContext类来执行数据库操作。现在我们来看下数据库理论中的多样性关系,我们会使用Code First来实现下面的几种关系:

首先要明确关系的概念。关系就是定义两个或多个对象之间是如何关联的。它是由关系两端的多样性值识别的,比如,一对多意味着在关系的一端,只有一个实体,我们有时称为父母;在关系的另一端,可能有多个实体,有时称为孩子。EF API将那些端分别称为主体和依赖。一对多关系也叫做一或零对多(One-or-Zero-to-Many),这意味着一个孩子可能有或可能没有父母。一对一关系也稍微有些变化,就是关系的两端都是可选的。

Entity Framework如何管理一对一实体关系

一、EF里的实体关系配置

Has方法

Entity Framework如何管理一对一实体关系

With方法

Entity Framework如何管理一对一实体关系

配置实体关系:

Entity Framework如何管理一对一实体关系

一对一表关系设计:

Entity Framework如何管理一对一实体关系

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

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

示例中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{    /// <summary>    /// 主表    /// </summary>    [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; }        /// <summary>        /// virtual 表示是导航属性 启用贪懒加载        /// </summary>        [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; }        /// <summary>        /// 导航属性        /// </summary>        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 DbSet<Person> Persons { get; set; }        public DbSet<IDCard> 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{    /// <summary>    /// 主表    /// </summary>    [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; }        /// <summary>        /// virtual 表示是导航属性 启用贪懒加载        /// </summary>        [ForeignKey("PersonId")]        [Required]        public virtual IDCard IDCard { get; set; }    }}

4、查看生成的数据库表结构

Entity Framework如何管理一对一实体关系

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

总结:使用数据注解配置一对一关系的步骤:

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

感谢各位的阅读!关于“Entity Framework如何管理一对一实体关系”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯