随笔 - 2  文章 - 0  评论 - 0  阅读 - 1268

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,定义类如下:

1
2
3
4
5
6
7
8
9
10
11
12
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; }
 
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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:

1
2
3
4
5
6
7
8
9
10
11
12
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
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方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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});
     
}

 运行数据库更新命令,实体和数据库模型就建好了。

 

posted on   ZhouAlex  阅读(1094)  评论(0编辑  收藏  举报
编辑推荐:
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
< 2025年2月 >
26 27 28 29 30 31 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 1
2 3 4 5 6 7 8

点击右上角即可分享
微信分享提示