EF Core创建实体的Code First标准方法
针对关系型数据库,实体之间的关系最常见的就是通过外键关联的一对一、一对多和多对多的关系,新的ef core通过注释和fluent api 能够做到接近于数据库通过dml创建模型的效果了。实际上,通过dml 最大的优势在于,能够定义所谓的independent/dependent entity具体的那个字段作为关联字段,而ef更多通过一种约定去描述这种关联关系,不过通过fluent api 能够收工定义的操作范围更近广了。
下面的这个表关系实际上描述了大部分关系型数据库的关联关系,能够覆盖大部分场景,通过这个例子去说明code first 创建实体的标准方法。
members 和tasks 关系,member是independent entity, tasks是dependent entity,定义类如下:
namespace membertask.models
{
public partial class members
{
[key]
public int? memberid { get; set; }
public string membername { get; set; }
[inverseproperty("members")]
public list<tasks> tasks { get; set; }
}
}
namespace membertask.models
{
public partial class tasks
{
[key]
public int? taskid { get; set; }
public int taskname { get; set; }
public int memberid { get; set; }
[foreignkey("memberid")]
public members members { get; set; }
//part of many2many
[inverseproperty("task")]
public list<taskandoatasksr> taskandoatasksrs { get; set; }
}
}
在这两个实体的关系中:
先看tasks类(红色字体部分),通过注释指明,memberid 字段作为外键,而members引用导航属性,作为外键所关联依赖的对象。
members类,tasks 列表导航属性就是被引用对象,而注释表明members 就是tasks中的引用导航属性members。
另外3个实体店关系为,tasks和oatasks是业务实体,taskandoatasksrs实际上作为一个中间表,提供一种多对多的关系,这种模式实际上是作为灵活的一种实体模式,虽然有一定的空间损耗,但是无论哪种关系,或者未来需要扩展成为多对多的关系可以随时实施。
oatasks:
namespace membertask.models
{
public partial class oatasks
{
[key]
public int? oataskid { get; set; }
public string oataskname { get; set; }
[inverseproperty("oatask")]
public list<taskandoatasksr> taskandoatasksrs { get; set; }
}
}
tasksandoatasksrs:
namespace membertask.models
{
public partial class taskandoatasksr
{
public int? taskid { get; set; }
[foreignkey("taskid")]
public tasks task { get; set; }
[foreignkey("oataskid")]
public int? oataskid { get; set; }
public oatasks oatask { get; set; }
}
}
tasksandoatasksrs在实际上使用的时候,是不需要实现taskid查询关联的多个oataskid的,仅仅查询taskid & oataskid 的一一对应关系,因此通过引用导航属性引用tasks 和oatasks。相反,tasks 和oatasks都有需要进行一对多关联查询,因此采用了列表导航属性。
模型建好后,根据实际情况配置dbcontext,特别是针对外键关联,根据实际情况定义好ondelete方法。
protected override void onmodelcreating(modelbuilder modelbuilder)
{
modelbuilder.entity<members>()
.property(b => b.memberid).valuegeneratednever();
modelbuilder.entity<tasks>()
.property(t => t.taskid).valuegeneratednever();
modelbuilder.entity<oatasks>()
.property(o => o.oataskid).valuegeneratednever();
modelbuilder.entity<tasks>()
.hasone(m=>m.members)
.withmany(t=>t.tasks)
.ondelete(deletebehavior.cascade);
// below is for many2many
modelbuilder.entity<taskandoatasksr>()
.hasone(t => t.task)
.withmany(tt => tt.taskandoatasksrs);
modelbuilder.entity<taskandoatasksr>()
.hasone(t => t.oatask)
.withmany(tt => tt.taskandoatasksrs);
modelbuilder.entity<taskandoatasksr>()
.haskey(t => new {t.taskid, t.oataskid});
}
运行数据库更新命令,实体和数据库模型就建好了。
推荐阅读
-
【基于EF Core的Code First模式的DotNetCore快速开发框架】完成对DB First代码生成的支持
-
9.翻译系列:EF 6以及EF Core中的数据注解特性(EF 6 Code-First系列)
-
EF Core创建实体的Code First标准方法
-
DDD Code First 迁移数据实现EF CORE的软删除,值对象迁移配置
-
14.翻译系列:从已经存在的数据库中生成上下文类和实体类【EF 6 Code-First系列】
-
9.翻译系列:EF 6以及EF Core中的数据注解特性(EF 6 Code-First系列)
-
EF Core创建实体的Code First标准方法
-
ASP.NET Core 中使用EF Core 将实体映射到数据库表的方法(SQL Server)
-
DDD Code First 迁移数据实现EF CORE的软删除,值对象迁移配置
-
14.翻译系列:从已经存在的数据库中生成上下文类和实体类【EF 6 Code-First系列】