在关系型数据库中,表与表之间有如下关系:
One-to-One Relationships
One-to-many or Many to One Relationships
Many-to-Many Relationships
1:1 关系 —>比如每个人只能有一个唯一的身份证号码(Person:CardId)
1:N 关系 -->班级与学生(Class:Student)、产品类型与产品(ProductType:Product)等等
N:N 关系 ---->学生与老师(Student:Teacher)、学生与课程(Student:Course)等等
1.使用Fluent API配置1对多的实体关系
添加一个班级类Clazs:
public class Clazs
{
public int ClazsId { get; set; }
public string ClassName { get; set;}
/// <summary>
/// 配置1:N关系(导航属性:Students) class:student 双向关系
/// 通过Class可以找到相关联的所有Student记录
///
/// </summary>
public virtual ICollection<Student> Students { get; set; } = new List<Student>();
}
配置导航属性Students
在Student类中也配置导航属性:
public class Student
{
/// <summary>
/// EF的主键约定:Id或者是类名+Id
/// 既是主键又是标识列
/// </summary>
public long Id { get; set;}
public string Name { get; set;}
public int Age { get; set; }
public string Address { get; set; }
public DateTime CreateDateTime { get; set;}
public decimal Height { get; set; }
public int ClazsId { get; set; }
/// <summary>
/// 配置1:N关系(导航属性:Clazs) class:student
///
/// 通过Student可以找到相关联的Clazs
/// </summary>
public Clazs Clazs { get; set; }
}
将下面代码添加到数据库上下文类中:(切记)
public DbSet<Clazs> Classes { get; set;}
2.在实体配置文件的构造器中,配置1:N关系:
Class:Student -->1:N关系
StudentConfig配置类:
//配置1:N关系,ClazsId为必填
this.HasRequired(s => s.Clazs).WithMany().HasForeignKey(s => s.ClazsId);
ClazsConfig配置类:
//配置1:N关系 class:student --->1:n关系
this.HasMany(s => s.Students).WithRequired().HasForeignKey(s => s.ClazsId);
由于我们更改了实体类配置:
当创建好了数据库(手动创建或者是Code First模式下自动生成的)
当修改了模型类或者Context数据库上下类,
再次进行数据库交互时,会抛出异常,需要进行数据迁移操作
解决方案:
见之前写的博客: 数据迁移技术
测试用例:
public static void Test1ToNRelationShip() {
using (SchoolContext context = new SchoolContext())
{
Clazs clazs = new Clazs()
{
ClassName = "四年级二班"
};
context.Classes.Add(clazs);
Student student = new Student()
{
Address = "江苏南京",
Age = 27,
Clazs = clazs,//将已创建的Class对象与当前的Student记录建立起关联
CreateDateTime = DateTime.Now,
Name = "Yellow Dude",
Height = 178
};
context.Students.Add(student);
int count = context.SaveChanges();
if (count > 0)
{
Console.WriteLine("数据已成功添加!");
}
}
}
运行完成:记录已成功添加
基于1:N关系的数据查询,实际就是外键列值的匹配
测试案例:
Student student = context.Students.Include("Clazs").FirstOrDefault<Student>(s => s.Id == 3);
Clazs clazs = student.Clazs;
Clazs clazs02 = context.Classes.Include("Students").FirstOrDefault(c => c.ClazsId == 6);
Clazs clazs03 = context.Classes.FirstOrDefault(c => c.ClazsId == 6);
//查询和clazs2相关联的所有Student记录
List<Student> students = context.Students.Where(s => s.ClazsId == clazs03.ClazsId).ToList<Student>();
Include(string navgationName) -->参数为导航属性值:
实际在EF Code First模式下,使用了Fluent API配置了导航属性以及配置了实体之间的1:n关系,在查询时EF会根据导航属性,会将关联的记录也查询出来了。
查询clazs03,相关联的Student记录也查询出来了