目录
相关文章
【EntityFramework CodeFirst 轻松上手】(一) 让类的数据持久化更轻松
【EntityFramework CodeFirst 轻松上手】(二) 示例:安装 CodeFirst 开发环境
【EntityFramework CodeFirst 轻松上手】(三) 示例:新建 CodeFirst 实体类
【EntityFramework CodeFirst 轻松上手】(四) 示例:新建 CodeFirst 数据库会话 【DbContext、DbSet】
【EntityFramework CodeFirst 轻松上手】(五) 示例:使用 CodeFirst 数据会话和实体类
本章目录
4、使用 Data Annotation 特性标记 定制实体类到数据库对象的映射关系
5、使用 Fluent API 代码定制实体类到数据库对象的映射关系
1、准备建立两个简单的实体类
我们继续使用EntityFrameworkCodeFirst示例项目,准备在项目下添加一些简单的实体。我们假设为一个公司建立两个实体类,一个是部门(名为Department),另一个是员工(名为Staff),如图。
部门Department的属性:部门序号Id、部门编号Code、部门名称Name、部门员工列表Staffs。
员工Staff的属性:员工序号Id、员工编号Code、员工姓名Name、所属部门Department、所属部门序号DepartmentId。
部门Department与员工Staff的关系:每位员工Staff隶属于某个部门Department,一个部门Department可能包含多位员工Staff。
实体类的代码如下:
/// <summary>
/// 部门
/// </summary>
public class Department
{
/// <summary>
/// Id
/// </summary>
public long Id { get; set; }
/// <summary>
/// 编码
/// </summary>
public string Code { get; set; }
/// <summary>
/// 名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 员工集合
/// </summary>
public virtual ICollection<Staff> Staffs { get; set; }
}
/// <summary>
/// 员工
/// </summary>
public class Staff
{
/// <summary>
/// Id
/// </summary>
public long Id { get; set; }
/// <summary>
/// 编码
/// </summary>
public string Code { get; set; }
/// <summary>
/// 名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 所属部门Id
/// </summary>
public long DepartmentId { get; set; }
/// <summary>
/// 所属部门
/// </summary>
public virtual Department Department { get; set; }
}
2、实体类到数据库对象的默认映射关系
默认情况下,不需要特殊的语法或附加的语句,实体类就可以自动对应到数据库对象。做为数据库的主要对象数据表与实体类一一对应,数据表的字段与实体类的属性一一对应,大体上如此,如表所示:
数据库 | 实体类 | 示例 | |
实体类元素 | 数据库元素 | ||
表名 | 类名的复数形式 | Department、Staff | Departments、Staffs |
表格所有者 | dbo | dbo.Departments、dbo.Staffs | |
字段名 | 类的属性名 | Department.Code、Staff.Name | Departments.Code、Staffs.Name |
主键 | 名为“Id”或“类名Id”的属性 | Department.Id、Staff.Id | Departments.Id(PK_dbo.Departments)、Staffs.Id(PK_dbo.Staffs) |
外键 | 类型为其他实体的属性,或实现Icollection的集合属性且该集合的成员类型为其他实体 | Department.Staffs、Staff.Department | Staffs.DepartmentId(FK_dbo.Staffs_dbo.Departments_DepartmentId) |
3、定制实体类到数据库对象的映射关系
如果想更为细致地定义实体类型到数据库对象的对应关系,只需要附加少量的特殊的代码就好。具体有两种途径:使用 Data Annotation 特性标记、使用 Fluent API 代码。
4、使用 Data Annotation 特性标记 定制实体类到数据库对象的映射关系
为实体类添加引用
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
为实体类及其属性添加标记
/// <summary>
/// 部门
/// </summary>
public class Department
{
/// <summary>
/// Id
/// </summary>
[Key] //主键
public long Id { get; set; }
/// <summary>
/// 编码
/// </summary>
[Required] //必需的
[StringLength(100)] //字符串的最大长度
public string Code { get; set; }
/// <summary>
/// 名称
/// </summary>
[Required] //必需的
[StringLength(200)] //字符串的最大长度
public string Name { get; set; }
/// <summary>
/// 员工集合
/// </summary>
[InverseProperty("Department")] //导航属性的对应关系
public virtual ICollection<Staff> Staffs { get; set; }
}
/// <summary>
/// 员工
/// </summary>
public class Staff
{
/// <summary>
/// Id
/// </summary>
[Key] //主键
public long Id { get; set; }
/// <summary>
/// 编码
/// </summary>
[Required] //必需的
[StringLength(100)] //字符串最大长度
public string Code { get; set; }
/// <summary>
/// 名称
/// </summary>
[Required] //必需的
[StringLength(200)] //字符串最大长度
public string Name { get; set; }
/// <summary>
/// 所属部门Id
/// </summary>
public long DepartmentId { get; set; }
/// <summary>
/// 所属部门
/// </summary>
[ForeignKey("DepartmentId")] //导航属性对应的外键属性
public virtual Department Department { get; set; }
}
类似的特性还有很多,可以通过对象浏览器查看下列程序集:System.ComponentModel.DataAnnotations。每个特性其中包含摘要说明。如图。
5、使用 Fluent API 代码定制实体类到数据库对象的映射关系
两种方式异曲同工。我比较喜欢使用 Data Annotation 标记,和类的代码浑然一体,比较直观。从我个实践来看, Data Annotation 可以胜任大多数情况,但有时附加的 Fluent API 代码可以解决一些特殊需要。
下面我就来看看Fluent API,简单说,就是在上下文DbContext中重写一个事件:OnModelCreating(DbModelBuilder modelBuilder)。示例代码如下:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//Department
modelBuilder.Entity<Department>().HasKey(m=>m.Id); //主键
modelBuilder.Entity<Department>().Property(m => m.Code).IsRequired(); //必需的
modelBuilder.Entity<Department>().Property(m => m.Code).HasMaxLength(100); //字符串最大长度
modelBuilder.Entity<Department>().Property(m => m.Name).IsRequired().HasMaxLength(200); //必需的 //字符串最大长度
modelBuilder.Entity<Department>().HasMany(m => m.Staffs).WithRequired(m => m.Department).HasForeignKey(m => m.DepartmentId); //导航属性的对应关系及外键定义
//Staff
modelBuilder.Entity<Staff>().HasKey(m => m.Id); //主键
modelBuilder.Entity<Staff>().Property(m => m.Code).IsRequired(); //必需的
modelBuilder.Entity<Staff>().Property(m => m.Code).HasMaxLength(100); //字符串最大长度
modelBuilder.Entity<Staff>().Property(m => m.Name).IsRequired().HasMaxLength(200); //必需的 //字符串最大长度
}
两种方法可以互为补充或者重复,但不要有歧义。
要知DbContext如何以及更多内容,且听下回分解。
休息一会、休息一会儿吧。