现在使用多数的数据库是关系型数据库,那么表与表之间的关系就会显得尤其重要,对于数据的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);
}
}

数据库中的表

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

数据库中的表

三:多对多联系(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);
}
}

数据库中的表

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

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

出现错误

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

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

下面是数据上下文中的代码

    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);
}
}

数据库的连接字符串<App.Config>

  <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>

附件:

Fluent API参考

http://www.cnblogs.com/oppoic/p/ef_one-to-one_one-to-many_many-to-many_cascadedelete.html

http://www.cnblogs.com/panchunting/p/entity-framework-code-first-fluent-api-configuring-relationships.html

理解一对一关系

http://www.cnblogs.com/dudu/archive/2011/07/08/entity_framework_one_to_one_two_way.html

DB表的关系及EF中Fluent API的使用的更多相关文章

  1. EF使用Fluent API配置映射关系

    定义一个继承自EntityTypeConfiguration<>泛型类的类来定义domain中每个类的数据库配置,在这个自定义类的构造函数中使用我们上次提到的那些方法配置数据库的映射. 映 ...

  2. EF:Fluent API 把一对多映射为一对一

    假设有两张表:A表和B表.A表与B表在数据库中的关系是一对多,但我们需要在EF中映射为一对一. 首先在A实体类和B实体类中互相为对方增加一个实体类的属性: public A { public B B ...

  3. 第六节:框架搭建之EF的Fluent Api模式的使用流程

    一. 前言 沉寂了约一个月的时间,今天用一篇简单的文章重新回归博客,主要来探讨一下Fluent Api模式在实际项目中的使用流程. 1. Fluent API属于EF CodeFirst模式的一种,E ...

  4. EF Core Fluent API

    多对多配置 先安装 Install-Package MySql.Data.EntityFrameworkCore 创建3个表 创建类 public class Role { public long I ...

  5. 第十八篇 .NET高级技术之Linq与EF Code-First Fluent API基础讲解

    1.FluentApi简介 在这里提供了一个fluentapi基础的DEMO然后咱们在进一步的学习,直接上干货. 第一步在数据库创建一个表:person 第二步:新建控制台程序FluentAPI 第三 ...

  6. EF Core中Fluent Api如何删除指定数据表中的行

    这两天一直在研究在code first下如何删除数据表中的指定行,于是开始搜狗,后来百度,压根就找不到资料,后来一想可能我的搜索关键字有问题,而且ef core命令与ef的命令差不多,于是从这两个方面 ...

  7. 扩展EF的Fluent API中的 OnModelCreating方法 实现全局数据过滤器

    1.生成过滤的表达式目录树 protected virtual Expression<Func<TEntity, bool>> CreateFilterExpression&l ...

  8. 1.【使用EF Code-First方式和Fluent API来探讨EF中的关系】

    原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/relationship-in-entity-framework-using-code-firs ...

  9. Entity Framework 实体框架的形成之旅--Code First模式中使用 Fluent API 配置(6)

    在前面的随笔<Entity Framework 实体框架的形成之旅--Code First的框架设计(5)>里介绍了基于Code First模式的实体框架的经验,这种方式自动处理出来的模式 ...

随机推荐

  1. 【腾讯优测干货】看腾讯的技术大牛如何将Crash率从2.2%降至0.2%?

    小优有话说: App Crash就像地雷. 你怕它,想当它不存在.无异于让你的用户去探雷,一旦引爆,用户就没了. 你鼓起勇气去扫雷,它却神龙见首不见尾. 你告诫自己一定开发过程中减少crash,少埋点 ...

  2. [stm32] 一个简单的stm32vet6驱动2.4寸240X320的8位并口tft屏DEMO

    书接上文: 最近在研究用低速.低RAM的单片机来驱动小LCD或TFT彩屏实现动画效果 首先我用一个16MHz晶振的m0内核的8位单片机nRF51822尝试驱动一个1.77寸的4线SPI屏(128X16 ...

  3. Spring-Context之八:一些依赖注入的小技巧

    Spring框架在依赖注入方面是非常灵活和强大的,多了解点一些注入的方式.方法,绝对能优化配置. idref idref属性可以传入一个bean的名称,虽然它是指向一个bean的引用,但是得到的是该b ...

  4. mongodb java spring data

    关于如何集成spring-data-mongodb到项目中,已经有很多人介绍了,这里只给出几个链接. GETTING STARTED Accessing Data with MongoDB: http ...

  5. Infinispan 8 中新的 Redis 缓存存储实现

    转载于:http://www.itxuexiwang.com/a/shujukujishu/redis/2016/0216/147.html nfinispan 8 包含了一个新的在 Redis k/ ...

  6. 前端那点事儿——Tocify自动生成文档目录

    今天偶然间看到文档服务器有一个动态目录功能,点击目录能跳转到指定的位置:窗口滑动也能自动更新目录的焦点. 效果 框架 原来使用的是一个开源的jquery-ui控件——tocify.js,它可以遍历页面 ...

  7. struts2学习笔记之九:struts2的命名空间

    struts2的命名空间适用于多人开发,根据不同模块命名不同的命名空间,方便开发和管理 struts2如果没有配置命名空间,默认命名空间为"/",Struts2中Action的完整 ...

  8. [Spring框架]Spring JDBCTmplate基础入门总结.

    前言:前面有讲过 Spring IOC以及AOP的基本使用方法, 这里就再来讲下Spring JDBCTemplate的使用方法. 一, 概述这里先说一下Spring 整合的一些模板: 从上图中可以看 ...

  9. atitit.事件驱动的总结attilax

    atitit.事件驱动的总结attilax Keyboard 基于的的ed 与  mouse 基础的ed Kb  base on focus ....   Mouse base on mouse mo ...

  10. salesforce 零基础学习(三十)工具篇:Debug Log小工具

    开发中查看log日志是必不可少的,salesforce自带的效果显示效果不佳,大概显示效果如下所示: chrome商城提供了apex debug log良好的插件,使debug log信息更好显示.假 ...