DB表的关系及EF中Fluent API的使用

简介: DB表的关系及EF中Fluent API的使用

现在使用多数的数据库是关系型数据库,那么表与表之间的关系就会显得尤其重要,对于数据的CRUD处理和以后数据的分析有很大的好处。下面是对于数据库中对表关系的理解以及在EF中使用Fluent API来创建这种关系的例子.




数据库中实体之间的联系


书中语录:在现实世界中,事务内部以及事务之间是有联系的,这些联系在计算机里面叫做实体之间的联系和实体内部的联系,内部的联系就是组成实体属性之间的联系,而实体之间的联系可以分为三类。(1:1, 1:n, n:n)




一:一对一联系(1:1)


  A实体集中每一个实体在实体集B中至多有一个实体与之联系,反之亦然,这就是一对一联系。


eg:一个班只有一个班长,而一个班长只在一个班中任职。班级与班长就是一对一关系。




 属性模型


/// <summary>
/// Monitor代表班长类
/// </summary>
public class Monitor
{
    public Guid MonitorId { get; set; }
    public string MName { get; set; }
    public int MAge { get; set; }
    public virtual TheClass TheClass { get; set; }                        //导航属性
}
/// <summary>
/// TheClass表示班级
/// </summary>
public class TheClass
{
    public TheClass()
    {
        this.Students = new HashSet<Student>();
    }
    public virtual Monitor Monitor { get; set; }                          // 导航属性   
     public Guid TheClassId { get; set; }
    public string TcName { get; set; }
    public int TcNumber { get; set; }
    public virtual ICollection<Student> Students { get; set; }            //班级里面有很多学生
}




Fluent API(1:1)


public class MonitorMap : EntityTypeConfiguration<Monitor>
{
    public MonitorMap()
    {
        this.ToTable("Monitor");
        this.HasKey(x=>x.MonitorId);            
        Property(x => x.MName).HasMaxLength(128);
        Property(x => x.MAge);
        this.HasRequired(x => x.TheClass).WithOptional(x => x.Monitor).Map(x => x.MapKey("TheClassId"));    //这里设置Monitor为依赖类,且TheClassId为外键。            
    }
}
public class TheClassMap:EntityTypeConfiguration<TheClass>
{
    public TheClassMap()
    {
        ToTable("TheClass");
        HasKey(x => x.TheClassId);
        Property(x => x.TcName).HasMaxLength(128);
        Property(x => x.TcNumber);
        HasMany(x => x.Students);              
        HasOptional(x => x.Monitor);               
    }
    }



数据库中的表


679140-20151031180644466-690844947.png

 在实现一对一的过程中,出现了很多的问题,说是外键设置的问题,依赖类和主类关系不清.这些刚开始的时候一直出错,导致数据库中模型创建不了,浪费很长时间,出现这种情况就是我们代码里面设置的问题,此时我们百度,博客园等均可解决  ,上面Fluent API代码中是正确的。



二:一对多联系(1:n)


  A实体集中每一个实体在B实体集中有n个实体与之对应(n>=0),反过来,B实体集中的每一个实体在A中只有1个与之对应。这种形式就是一对多联系。


eg:班集和班集里面学生的关系。学校和学生的关系。


属性

/// <summary>
/// TheClass表示班级
/// </summary>
public class TheClass
{
    public TheClass()
    {
        this.Students = new HashSet<Student>();
    }
    public virtual Monitor Monitor { get; set; }                                  // 导航属性   
     public Guid TheClassId { get; set; }
    public string TcName { get; set; }
    public int TcNumber { get; set; }
    public virtual ICollection<Student> Students { get; set; }            //班级里面有很多学生
}
/// <summary>
/// 学生表
/// </summary>
  public class Student
{
    public Student()
    {
        this.Courses=new Collection<Course>();
    }
    public Guid StudentId { get; set; }
      public string SName { get; set; }
      public int SAge { get; set; }
      public Guid TheClassId { get; set; }
      public virtual  TheClass TheClass { get; set; }          //学生属于一个班级
    public virtual ICollection<Course> Courses { get; set; }
}



Fluent API(1:n)


public class TheClassMap:EntityTypeConfiguration<TheClass>
{
    public TheClassMap()
    {
        ToTable("TheClass");
        HasKey(x => x.TheClassId);
        Property(x => x.TcName).HasMaxLength(128);
        Property(x => x.TcNumber);
        HasMany(x => x.Students);              
        HasOptional(x => x.Monitor);               
    }
}
public class StudentMap : EntityTypeConfiguration<Student>
{
    public StudentMap()
    {
        ToTable("Student");
        HasKey(x => x.StudentId);
        Property(x => x.SName).HasMaxLength(128);
        HasRequired(x => x.TheClass).WithMany(x => x.Students).HasForeignKey(x => x.TheClassId);
        HasMany(x => x.Courses).WithMany(x => x.Student);
    }
}



数据库中的表



679140-20151031180159560-1145601168.png



三:多对多联系(n:n)


A实体集中的每一个实体在实体集B中有n个实体与之对应(n>=0),反过来,B实体集中每一个实体在实体集A中有m个实体与之对应,这种关系就是多对多联系。

eg:学生和选修课。(一个学生可选修多门课程,一门课程可由多名学生选修),订单和产品(一个订单里面有多个产品,一个产品可在多个订单中)。



属性模型


/// <summary>
/// 课程类
/// </summary>
public class Course
{
    public Course()
    {
        this.Student=new Collection<Student>();
    }
    public Guid CourseId { get; set; }
    public string CName { get; set; }
    public virtual ICollection<Student> Student { get; set; }
}
/// <summary>
/// 学生表
/// </summary>
  public class Student
{
    public Student()
    {
        this.Courses=new Collection<Course>();
    }
      public Guid StudentId { get; set; }
      public string SName { get; set; }
      public int SAge { get; set; }
      public Guid TheClassId { get; set; }
      public virtual  TheClass TheClass { get; set; }          //学生属于一个班级
       public virtual ICollection<Course> Courses { get; set; }
}


Fluent API


public class CourseMap:EntityTypeConfiguration<Course>
{
    public CourseMap()
    {
        ToTable("Course");
        HasKey(x => x.CId);
        Property(x => x.CName).HasMaxLength(128);
        HasMany(x => x.Students).WithMany(x=>x.Courses).Map(m =>
        {
            m.ToTable("CourseStudentId");
            m.MapLeftKey("CourseId");
            m.MapRightKey("StudentId");
        });                                                     //这里设置多对多关系中间表的表名和列名
    }
public class StudentMap:EntityTypeConfiguration<Student>
{
    public StudentMap()
    {
        ToTable("Student");
        HasKey(x => x.SId);
        Property(x => x.SName).HasMaxLength(128);
        HasRequired(x => x.TheClass).WithMany(x=>x.Students).HasForeignKey(x=>x.TheClassId);
        HasMany(x => x.Courses).WithMany(x=>x.Students);
    }
}

数据库中的表


679140-20151031180201216-1628261470.png

在多对多关系中,我们可以设置中间表的表名和列名,就如同上面那样子。


  上面就是数据库表的三中关系,其中里面的一对一是一对多的特例,一对多是多对多的特例,我们只有掌握好这些最基本的知识,才能理解更加复杂表中的关系。


出现错误


679140-20151031180201872-1893145911.png


*:这是我在使用数据迁移的时候出现的错误。原因是我前面的主键设置的是(SId,CId,TCId,MId).EF在生成数据库的时候报错,我们应该把他们设置为(StudentId,CourseId,TheClassId,MonitorId),这样子就会出现我们的表。


* 上面的错误很大一定程度是因为我没有重写EF里面的OnModelCreating类导致的,我前面多对多表创建时出现的问题也是由于这个原因导致的。


679140-20151031180203482-829821110.png


下面数据上下文中的代码


public class BlogDbContent : DbContext, IDisposable
{
    public BlogDbContent()
        : base("name=BlogsEntities")
    {
    }
    public DbSet<BlogUser> BlogUser { get; set; }
    public DbSet<Post> Post { get; set; }
    public DbSet<Course> Course { get; set; }
    public DbSet<Student> Students { get; set;}
    public DbSet<TheClass> TheClass { get; set; }
    public DbSet<Monitor> Monitor { get; set; }
    /// <summary>
    /// 重写配置类
    /// </summary>
    /// <param name="modelBuilder"></param>
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        var typesToRegister = Assembly.GetExecutingAssembly().GetTypes()
        .Where(type => !String.IsNullOrEmpty(type.Namespace))
        .Where(type => type.BaseType != null && type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>));
        foreach (var type in typesToRegister)
        {
            dynamic configurationInstance = Activator.CreateInstance(type);
            modelBuilder.Configurations.Add(configurationInstance);
        }
        base.OnModelCreating(modelBuilder);
    }
}


数据库的连接字符串


<connectionStrings>
  <add name="BlogsEntities" connectionString="Data Source=localhost;Initial Catalog=Ahui_Blog;Integrated Security=False;
       Persist Security Info=False;User ID=sa;Password=******" providerName="System.Data.SqlClient" />
</connectionStrings>



目录
相关文章
|
2月前
|
SQL API Python
Python DB API下规范下cursor对象常用接口
Python DB API下规范下cursor对象常用接口。
35 4
|
2月前
|
Java API Android开发
[NDK/JNI系列04] JNI接口方法表、基础API与异常API
[NDK/JNI系列04] JNI接口方法表、基础API与异常API
27 0
|
2月前
|
前端开发 BI API
钉钉多维表目前没有提供具体的API文档供开发者调用
【2月更文挑战第17天】钉钉多维表目前没有提供具体的API文档供开发者调用
111 4
|
2月前
|
SQL 分布式计算 DataWorks
DataWorks常见问题之API同步接入maxcomputer表如何解决
DataWorks是阿里云提供的一站式大数据开发与管理平台,支持数据集成、数据开发、数据治理等功能;在本汇总中,我们梳理了DataWorks产品在使用过程中经常遇到的问题及解答,以助用户在数据处理和分析工作中提高效率,降低难度。
|
12月前
|
存储 SQL 关系型数据库
PG通过表访问方法API如何执行顺序扫描
PG通过表访问方法API如何执行顺序扫描
98 0
Paddle 1.8 与 Paddle 2.0 API 映射表
本文档基于 Paddle 1.8 梳理了常用 API 与 Paddle 2.0 对应关系。你可以根据对应关系,快速熟悉 Paddle 2.0 的接口使用。
|
JSON API Go
go语言实现调用阿里云api,获取hostname和ip字段值,输出exl表
go语言实现调用阿里云api,获取hostname和ip字段值,输出exl表
262 0
go语言实现调用阿里云api,获取hostname和ip字段值,输出exl表
|
SQL 监控 关系型数据库
API参考—性能参数表
本文分别介绍了计算节点、数据/GMS节点、CDC节点的监控参数和含义。
|
API 分布式数据库 开发者
判断表是否存在_旧 API|学习笔记
快速学习 判断表是否存在_旧 API
判断表是否存在_旧  API|学习笔记
|
Java API 分布式数据库
判断表是否存在_新 API |学习笔记
快速学习 判断表是否存在_新 API