首页 > 编程语言 >asp.net core系列 26 EF模型配置(实体关系)

asp.net core系列 26 EF模型配置(实体关系)

时间:2023-04-18 09:44:20浏览次数:58  
标签:core 26 asp string get Blog set public 属性

一.概述

  EF实体关系定义了两个实体互相关联起来(主体实体和依赖实体的关系,对应数据库中主表和子表关系)。 在关系型数据库中,这种表示是通过外键约束来体现。本篇主要讲一对多的关系。先了解下描述关系的术语。

  (1) 依赖实体: 这是包含外键属性的实体(子表)。有时称为 child 。

  (2) 主体实体: 这是包含主/备用键属性的实体(主表)。 有时称为 parent。

  (3) 外键:依赖实体(子表)中的属性,用于存储主表的主键属性的值。

  (4) 主键: 唯一标识的主体实体(主表)的属性。 这可能是 primary key 或备用键。

  (5) 导航属性: 包含对相关实体引用,在的主体和或依赖实体上定义的属性。

    集合导航属性: 一个导航属性,对多个相关实体的引用。

    引用导航属性: 一个导航属性,对单个相关实体的引用。

 

         下面示例代码来说明Blog和Post之间的一对多关系。其中 Post 是依赖实体;Blog 是主体实体;Post.BlogId 是外键;Blog.BlogId 是主键;Post.Blog引用导航属性;Blog.Posts集合导航属性。

复制代码
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    public List<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public int BlogId { get; set; }
    public Blog Blog { get; set; }
}
复制代码

 

二.约定

  按照约定,当在实体类型上发现导航属性时,将创建关系。如果属性所指向的类型不能被当前数据库提供程序映射为标量类型,则将其视为导航属性。下面用三个示例来说明通过约定创建的主从实体关系。

 

  2.1 完全定义的关系

    关系最常见的模式是在关系的两端定义导航属性,并在依赖实体类中定义外键属性。

    (1)如果两个类型之间找到一对导航属性,则它们将被配置为同一关系的反转导航属性。

    (2)如果依赖实体包含名为的属性<primary key property name>, <navigation property name><primary key property name>,或<principal entity name><primary key property name>然后它将配置为外键。

    下面代码示例是完全定义的关系的实体,通过约定来创建主从实体关系。

复制代码
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
    //反转导航属性
    public List<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    //通过约定(<primary key property name>)创建外键
    public int BlogId { get; set; }
    //反转导航属性
    public Blog Blog { get; set; }
}
复制代码

    使用EF基于数据模型(Blog和Post实体)创建数据库。生成后,查看数据表的关系映射,如下图所示:

    

  2.2  没有外键属性

    虽然建议在依赖实体类中定义外键属性,但这不是必需的。如果没有找到外键属性,那么将引入一个名为<navigation property name> > principal key property name>的隐藏外键属性(上篇有介绍)。在下面代码中,依赖实体Post中没有显示定义外键BlogId。

复制代码
public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public Blog Blog { get; set; }
}
复制代码

 

   2.3 单一导航属性

     仅包含一个导航属性(没有反转导航属性,也没有外键属性)就足以拥有约定定义的关系。还可以有一个导航属性和一个外键属性。代码如下所示产:

复制代码
    public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    public List<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
}
复制代码

 

 三. 数据注释

   有两个数据注释可用于配置关系,[ForeignKey]和[InverseProperty]。

  3.1 ForeignKey可以将指定属性设置为外键属性。 这种设置通常是外键属性不被约定发现时,显示设置。如下面代码示例, 在依赖实体Post中将BlogForeignKey指定为外键。代码中生成的主从实体关系与上面的约定示例是一样的。

复制代码
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    public List<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public int BlogForeignKey { get; set; }

    [ForeignKey("BlogForeignKey")]
    public Blog Blog { get; set; }
}
复制代码

   下面使用EF基于数据模型(Blog和Post实体)创建数据库。生成后,查看数据表的关系映射,如下图所示:

 

  3.2 InverseProperty配置依赖实体和主体实体上的导航属性如何配对。当两个实体类型之间有一对以上的导航属性时,通常会这样做。如下面代码示例:

复制代码
     public class Post
    {
        public int PostId { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }

        public Blog Blog { get; set; }

        public User Author { get; set; }

        public User Contributor { get; set; }
    }

    public class User
    {
        public string UserId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }

        [InverseProperty("Author")]
        public List<Post> AuthoredPosts { get; set; }

        [InverseProperty("Contributor")]
        public List<Post> ContributedToPosts { get; set; }
    }
复制代码

    下面使用EF基于数据模型(User和Post实体)创建数据库。生成后,查看数据表的关系映射,如下图所示:

 

四. Fluent API

   要在Fluent API中配置关系,首先要确定组成关系的导航属性。HasOne或HasMany标识开始配置的实体类型上的导航属性。然后调用WithOneWithMany来标识反导航。HasOne/WithOne用于引用导航属性,而HasMany/WithMany用于集合导航属性。

  在EF基于现有数据库进行反向工程时,根据数据库将自动生成DbContext上下文类,里面重写了OnConfiguring方法。下面示例是一个MyContext上下文类,在OnModelCreating方法中确定了实体的关系。

  

  4.1 完全定义的关系

复制代码
    class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Post>()
            .HasOne(p => p.Blog) //Post类有一个Blog引用导航属性
            .WithMany(b => b.Posts);//Blog类有一个Posts反导航集合
    }
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
    //反导航集合
    public List<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    //引用导航属性
    public Blog Blog { get; set; }
}
复制代码

 

  4.2 单一导航属性

    如果只有一个导航属性,那么就会出现无参数重载的WithOne以及WithMany。这表明在关系的另一端有一个概念上的引用或集合,但是实体类中不包含导航属性。

复制代码
class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .HasMany(b => b.Posts)//blog类有一个集合导航属性
            .WithOne();
    }
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    public List<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
}
复制代码

    下面使用EF基于数据模型(User和Post实体)创建数据库。生成后,查看数据表的关系映射,如下图所示:

  4.3 外键

    可以使用 Fluent API 配置哪些属性应用作给定关系外键属性。

复制代码
    class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Post>()
            .HasOne(p => p.Blog)
            .WithMany(b => b.Posts)
            .HasForeignKey(p => p.BlogForeignKey);
    }
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    public List<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public int BlogForeignKey { get; set; }
    public Blog Blog { get; set; }
}
复制代码

    以下代码列表演示如何配置复合外键。

复制代码
class MyContext : DbContext
{
    public DbSet<Car> Cars { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Car>()
            .HasKey(c => new { c.State, c.LicensePlate });

        modelBuilder.Entity<RecordOfSale>()
            .HasOne(s => s.Car)
            .WithMany(c => c.SaleHistory)
            .HasForeignKey(s => new { s.CarState, s.CarLicensePlate });
    }
}

public class Car
{
    public string State { get; set; }
    public string LicensePlate { get; set; }
    public string Make { get; set; }
    public string Model { get; set; }

    public List<RecordOfSale> SaleHistory { get; set; }
}

public class RecordOfSale
{
    public int RecordOfSaleId { get; set; }
    public DateTime DateSold { get; set; }
    public decimal Price { get; set; }

    public string CarState { get; set; }
    public string CarLicensePlate { get; set; }
    public Car Car { get; set; }
}
复制代码

 

  总结:关于实体关系,还讲到了“必需和可选的关系”、“级联删除”。以及关系模式中的“一对一关系”、“多对多关系",这些以后用到再参考文档。 个人认为在传统开发中,以建库建表优先的情况下,不会去设置数据表的外键关系,这种关系是由编程去控制。 这样对数据库进行反向工程时,也不会生成有关系的主从实体模型。

 

 参考文献:

    官方文档:EF 实体关系

 

作者:花阴偷移

出处:https://www.cnblogs.com/MrHSR/

本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。

标签:core,26,asp,string,get,Blog,set,public,属性
From: https://www.cnblogs.com/Alex80/p/17328458.html

相关文章

  • ASP.NET Core MVC 从入门到精通之布局
    随着技术的发展,ASP.NETCoreMVC也推出了好长时间,经过不断的版本更新迭代,已经越来越完善,本系列文章主要讲解ASP.NETCoreMVC开发B/S系统过程中所涉及到的相关内容,适用于初学者,在校毕业生,或其他想从事ASP.NETCoreMVC系统开发的人员。 经过前几篇文章的讲解,初步了解ASP.NETCor......
  • 网络安全工程师教你:Kali Linux之Metasploit渗透测试基础(四)
    本分享仅做学习交流,请自觉遵守法律法规!搜索:Kali与编程,学习更多网络攻防干货!下篇文章将在明天下午五点发布,敬请关注!Metasploit渗透测试框架基础(四)一、背景介绍Metasploit就是一个漏洞框架。它的全称叫做TheMetasploitFramework,简称叫做MSF。Metasploit作为全球最受欢迎的工具,不......
  • CefSharp 启动 未能加载由"CefSharp.Core.Runtime.dll"导入的过程
    系统:Windows8.1CefSharp:112.2.70(当前最新稳定版)完整报错信息System.IO.FileLoadException:“未能加载由“CefSharp.Core.Runtime.dll”导入的过程。”  解决Readme.txt中已表示CefSharp109以后的版本不支持Windows10以下的操作系统:也就是说,如果是Windows10以下操......
  • 2642. 设计可以求最短路径的图类
    题目链接:2642.设计可以求最短路径的图类方法一:Dijkstra解题思路每次调用\(shortestPath(st,ed)\)时,就通过\(Dijkstra\)算法计算\(st\)->\(ed\)的最短路。代码朴素写法classGraph{private:vector<vector<int>>adj;inte[110][110],n;public:G......
  • 洛谷T226686 长度为2的子串
    题目描述给你一个长度为n 的由大写的英文字母组成的字符串,请你找出出现频率最高的长度为2的子串。输入格式包括两行。第一行是一个正整数n,表示字符串长度。第二行是长度为n的大写英文字母组成的字符串。(2<=n<=100)输出格式包括一行。一个长度为2的字符串,该字符串为输入......
  • gcore的学习
    gcore的学习-解决jmap无法生成dump文件的一种方法背景周末在跆拳道馆看孩子练跆拳道.开着笔记本翻到了扣钉日记公众号里面的讲解想着自己也遇到过无法保存dump文件的情况.所以想学习一下.进行联系其实之前也验证过宕机时的dump文件.感觉是比较类似的.gcoreNAME......
  • How to use the Raspberry Pi to study the Linux kernel source code All In One
    HowtousetheRaspberryPitostudytheLinuxkernelsourcecodeAllInOne如何利用树莓派来研究Linux内核源码AllInOnehttps://github.com/torvalds/linux学习笔记在Linux系统中,一切皆文件!(......
  • abp(net core)+easyui+efcore实现仓储管理系统——模块管理升级之上(六十一)
     Abp(netcore)+easyui+efcore实现仓储管理系统目录abp(netcore)+easyui+efcore实现仓储管理系统——ABP总体介绍(一)abp(netcore)+easyui+efcore实现仓储管理系统——解决方案介绍(二)abp(netcore)+easyui+efcore实现仓储管理系统——领域层创建实体(三) abp(netcore)+e......
  • Raspberry PI 设置开机自启动脚本 All In One
    RaspberryPI设置开机自启动脚本AllInOnedocsraspi-config$sudoraspi-confighttps://www.raspberrypi.com/documentation/computers/configuration.html#raspi-configconfig.txt$cat/boot/config.txt$sudonano/boot/config.txt$sudovim/boot/config.t......
  • 【CVE-2017-12615】Tomcat 远程代码执行漏洞复现
    0x00环境搭建用vulhub的环境查看配置文件conf/web.xml中readonly的设置0x01漏洞复现访问主页,抓包后修改数据包可通过PUT方式创建一个JSP文件。虽然Tomcat对文件后缀有一定检测(不能直接写jsp),但我们使用一些文件系统的特性(如Linux下可用/)来绕过了限制。改完包的时候......