一、概览
Part3-17:EF Core单向导航属性_哔哩哔哩_bilibili
二、双向导航属性
2.1、什么是双向导航属性?
可以从一端获取多端信息,也可以从多端获取一端信息。
2.2、双向导航属性在某些场景会产生麻烦
例如:在实际场景中用户表需要被许多其它业务表所使用,如果需要双向导航,就需要在用户表里面实现很多反向的导航属性,这样会让用户表非常复杂,这里用单向导航会更好,只需要多端指向一端。
双向导航样例
三、单向导航属性
3.1、图中例子:用户表+请假单,多端指向一端,一端不指向多端。
3.2、单向导航属性代码实现:多端实体类 Leave
namespace EFCorePart14
{
class Leave
{
public long Id { get; set; }
public User Requester { get; set; } //申请人
public User Approver { get; set; } //审批人
public string Remark { get; set; }
}
}
3.3、单向导航属性代码实现:一端实体类 User (不同于常规的一对多配置,这里不在一端实体表配置指向多端的字段)
class User
{
public long Id { get; set; }
public string Name { get; set; }
}
3.4、单向导航属性代码实现:多端配置类 LeaveConfig,因为一端没有指向多端的字段,所以WithMany()里面为空
特别注意:在EF6中,如果有两个外键,一定要加OnDelete(DeleteBehavior.Restrict),否则Update-database不通过会报错。
如果已经在没有加OnDelete(DeleteBehavior.Restrict)的情况下Add-Migration了,可以通过Remove-Migration命令删除生成的Migration,不加参数默认删除当前最新Migration。
namespace EFCorePart14
{
class LeaveConfig : IEntityTypeConfiguration<Leave>
{
public void Configure(EntityTypeBuilder<Leave> builder)
{
builder.ToTable("Leaves_Test");
builder.HasOne<User>(a => a.Requester).WithMany().IsRequired().OnDelete(DeleteBehavior.Restrict); ;
builder.HasOne<User>(a => a.Approver).WithMany().OnDelete(DeleteBehavior.Restrict);
}
}
}
3.4、单向导航属性代码实现:一端配置类 UserConfig,因为一端没有指向多端的字段,所有这里不配置关系连接。
namespace EFCorePart14
{
class UserConfig : IEntityTypeConfiguration<User>
{
public void Configure(EntityTypeBuilder<User> builder)
{
builder.ToTable("Users_Test");
}
}
}
3.5、生成的表外键:RequesterId、ApproverId
RequesterId
ApproverId
3.6、查询语句生成的SQL
var lea = db.Leaves.FirstOrDefault();
if(lea !=null)
{
Console.WriteLine(lea.Remark);
}
3.7、插入语句生成的SQL
User u2 = new User { Name = "小科" };
Leave l1 = new Leave { Remark = "回家处理拆迁事宜" ,Requester=u2};
db.Leaves.Add(l1);
db.SaveChanges();
四、选择
- 对于主从结构的“一对多”表关系,一般是声明双向导航属性。例如:采购单与采购明细
- 而对于其他的“一对多”表关系:如果表属于被很多表引用的基础表,则用单项导航属性,否则可以自由决定是否用双向导航属性。例如:用户信息与【请假、报销、采购】