Entity Framework 一对一关系映射

简介: Entity Framework 一对一关系映射

一对一关系是Entity Framework 中很复杂的关系,涉及了 HasOptional WithRequired WithOptionalPrincipal WithOptionalDependent。这篇文章我们将具体讲解这几个的用法。


我们以会员和订单为例,一个会员有可能有订单,也可能没有订单,但是一个订单绝对属于一个会员。我们先编写出会员和订单的类代码:

public class Member
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual Order Order { get; set; }
}
public class Order
{
    public int Id { get; set; }
    public int Name { get; set; }
    public int Num { get; set; }
    public virtual Member Member { get; set; }
}

零、 HasOptionl then WithRequired

这种方式的会员和订单的映射类如下:

public class MemberMap : EntityTypeConfiguration<Member>
{
    public MemberMap()
    {
        ToTable("Member");
        HasKey(p => p.Id);
        Property(p => p.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        HasOptional(p => p.Order).WithRequired(p => p.Member);
    }
}
public class OrderMap : EntityTypeConfiguration<Order>
{
    public OrderMap()
    {
        ToTable("Order");
        HasKey(p => p.Id);
        Property(p => p.Id).HasColumnName("MemberId")
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
    }
}

这里将 Member 类的Id设为自增长,将 Order 的Id设置别名 MemberId 且非自增长。编写晚上下文类和调用类后,运行代码后,我们在数据库中将看到如下图:1.png

其中 MemberId 就是在 OrderMap 中设置的别名

一、 HasOptionl then WithOptionalPrincipal

现在我们修改一下 MemberMap 和 OrderMap ,将 Member 和 Order 的Id都设置成自增长。

public class MemberMap : EntityTypeConfiguration<Member>
{
    public MemberMap()
    {
        ToTable("Member");
        HasKey(p => p.Id);
        Property(p => p.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        HasOptional(p => p.Order).WithOptionalPrincipal(p => p.Member);
    }
}
public class OrderMap : EntityTypeConfiguration<Order>
{
    public OrderMap()
    {
        ToTable("Order");
        HasKey(p => p.Id);
        Property(p => p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
    }
}

再次执行代码后,查看生成的数据库:

1.png

我们看到 Order 表中 Member_Id 字段是EF自动生成的外键,且不可为空

二、 HasOptionl then WithOptionalDependent

再次修改 MemberMap OrderMap

public class MemberMap : EntityTypeConfiguration<Member>
{
    public MemberMap()
    {
        ToTable("Member");
        HasKey(p => p.Id);
        Property(p => p.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        HasOptional(p => p.Order).WithOptionalDependent(p => p.Member);
    }
}
public class OrderMap : EntityTypeConfiguration<Order>
{
    public OrderMap()
    {
        ToTable("Order");
        HasKey(p => p.Id);
        Property(p => p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
    }
}

保存代码,运行程序,查看数据库:1.png

和上一小节生成的数据库相比,这一小节生成的数据库 Member 表中自动生成了 Order 表的外键 Order_Id ,而 Order 表没有生成任何外键。


注:使用 WithOptionalPrincipal 可以使实体作为主体,将包含关系主键。使用 WithOptionalDependent 可以使实体作为以来提,将包含关系的外键。


前面所讲的都是从 Member 入手,我们同样也可以从 Order 表入手,但是在实际开发中我不建议这么做。下面就来说一下从 Order 入手的方法。

三、 HasRequired then WithOptional

同样我们修改 MemberMap OrderMap

public class MemberMap : EntityTypeConfiguration<Member>
{
    public MemberMap()
    {
        ToTable("Member");
        HasKey(p => p.Id);
        Property(p => p.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
    }
}
public OrderMap()
{
    ToTable("Order");
    HasKey(p => p.Id);
    Property(p => p.Id).HasColumnName("MemberId").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
    HasRequired(p => p.Member).WithOptional(p => p.Order);
}

这种方法生成的数据库与第一种方法结果一样。

四、 HasRequired 和 WithOptional

我们最后一次修改 MemberMapOrderMap

public class MemberMap : EntityTypeConfiguration<Member>
{
    public MemberMap()
    {
        ToTable("Member");
        HasKey(p => p.Id);
        Property(p => p.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
    }
}
public class OrderMap : EntityTypeConfiguration<Order>
{
    public OrderMap()
    {
        ToTable("Order");
        HasKey(p => p.Id);
        Property(p => p.Id).HasColumnName("MemberId").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        HasRequired(p => p.Member).WithOptional(p => p.Order).Map(p => p.MapKey("Member_Id")))
    }
}

这种方法生成的数据库与第二种方法结果一样。

目录
相关文章
|
API 对象存储
腾讯云对象存储cos获取图片像素信息
简述获取图片像素信息的几种方案
腾讯云对象存储cos获取图片像素信息
|
索引 Python
Python 中的负索引是什么?
【8月更文挑战第29天】
731 1
|
Python
Python函数式编程:你真的懂了吗?理解核心概念,实践高阶技巧,这篇文章带你一次搞定!
【8月更文挑战第6天】本文介绍了Python中的函数式编程,探讨了高阶函数、纯函数、匿名函数、不可变数据结构及递归等核心概念。通过具体示例展示了如何利用`map()`和`filter()`等内置函数处理数据,解释了纯函数的一致性和可预测性特点,并演示了使用`lambda`创建简短函数的方法。此外,文章还强调了使用不可变数据结构的重要性,并通过递归函数实例说明了递归的基本原理。掌握这些技巧有助于编写更清晰、模块化的代码。
182 3
|
存储 安全 网络安全
网络安全的屏障与钥匙:漏洞、加密与意识的交织
【8月更文挑战第26天】在数字化浪潮中,网络安全成为保护数据和隐私的关键。本文深入探讨网络安全中的漏洞挖掘、加密技术的应用,以及提升个人和组织的安全防护意识的重要性。通过实例分析,我们揭示了网络攻击者如何利用漏洞进行入侵,展示了加密技术如何在数据传输和存储中起到防护作用,并强调了培养安全意识的必要性。文章旨在为读者提供一套综合性的网络安全防护策略,帮助构建更安全的网络环境。
|
11月前
|
分布式计算 Java 大数据
大数据-122 - Flink Time Watermark Java代码测试实现Tumbling Window
大数据-122 - Flink Time Watermark Java代码测试实现Tumbling Window
123 0
|
弹性计算 Java Linux
ECS使用体验的文章
ECS使用体验的文章
|
弹性计算 Shell Linux
|
Java Spring
使用JDBCTemplate实现与Spring结合,方法公用
使用JDBCTemplate实现与Spring结合,方法公用
|
网络协议 Unix 编译器
Windows Go 开发环境下载、安装并配置
Windows Go 开发环境下载、安装并配置
664 0
|
机器学习/深度学习 传感器 算法
【ANN预测】基于遗传算法优化 ANN附matlab代码
【ANN预测】基于遗传算法优化 ANN附matlab代码