2个表之间的关系 - 一对多和一对一(可空)EF代码优先
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2个表之间的关系 - 一对多和一对一(可空)EF代码优先相关的知识,希望对你有一定的参考价值。
我知道有很多关于这个问题的问题,但经过几天的思考后,我仍然无法弄清楚如何让它发挥作用。
我正在编写一个自动校准设备的应用程序。
我有2张桌子Transmitter
和Calibration
。
Transmitter
可以有零个,一个或多个Calibration
,Calibration
必须属于发射器。
现在Transmitter
应该有一个OfficialCalibration
,可以为null,例如在没有校准完成的时候。
所以我想在没有joiner表的情况下实现这个,只需在Transmitter
中有一个OfficialCalibrationId。 (两种方式我都需要更新2个表,但所以我的表总数更少)。也很好有这个关系作为navigationProperty所以我可以调用Transmitter.OfficialCalibration
并获得正确的Calibration
。
因此,如果没有EF Code First中的“加入”表,可以这样做吗?
我尝试使用一对多关系和一个附加约束来定义一对一的方法,但这样我有2个问题
- 我需要在校准中导航属性
Tranmitters
,我不想要 - 它不起作用,因为当我“注册”发射器时,ActualCalibrationId为空,因为此发射器没有校准。
现在我试过了:
modelBuilder.Entity(of Transmitter)
.HasMany(Function(c)c.Calibrations)
.WithRequired(Function(t)t.Transmitter)
.HasForeignKey(Function(t)t.TransmitterId)
但是仍然存在下图中显示的一对一关系的问题。
关系是Transmitter.Id
- > Calibration.Id
但应该是Transmitter.OfficialCalibrationId
- > Calibration.Id
这样我就不能强制校准只是一个OfficialCalibration
的Transmitter
吧?我可以用某种方式强行吗?我只能想到使用连接表Transmitter_DefaultCalbration
与列TransmitterId
和CalibrationId
并使TransmitterId
成为主键?
我仍在学习使用EF进行复杂的场景,所以任何信息或指导都会很好。
发送器 - 校准关系是1-n关系,因此您不需要连接表。
如您所知,您可以通过两种方式指定OfficialCalibration,在Transmitter上插入一个属性(Transmitter.OfficialCalibration)或在Calibration(Calibration.Default)中插入一个标志。两个关系都需要使用代码强制执行,因为: - 如果插入属性,则无法确定OfficialCalibration是与Transmitter相关的校准之一; - 如果插入标记,则无法确定只有一个正式校准。在写作时思考,可能这可以使用唯一索引来强制执行。
其他一些答案: - 通常,您不需要导航属性来定义关系(您只需要两个导航属性中的一个);
如果你不想要Calibrations属性,那么这就是C#中的模型
class Context : DbContext
{
public DbSet<Transmitter> Transmitters { get; set; }
public DbSet<Calibration> Calibrations { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Calibration>()
.HasRequired(_ => _.Transmitter);
}
}
class Calibration
{
public int Id { get; set; }
[MaxLength(50)]
public string Description { get; set; }
public virtual Transmitter Transmitter { get; set; }
}
class Transmitter
{
public int Id { get; set; }
[MaxLength(50)]
public string Description { get; set; }
public virtual Calibration OfficialCalibration { get; set; }
}
如果您首选默认属性,我将实现此模型(在这种情况下,我更喜欢具有Calibrations导航属性)
class Context : DbContext
{
public DbSet<Transmitter> Transmitters { get; set; }
public DbSet<Calibration> Calibrations { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Transmitter>()
.HasMany(_ => _.Calibrations)
.WithRequired(_ => _.Transmitter);
}
}
class Calibration
{
public int Id { get; set; }
[MaxLength(50)]
public string Description { get; set; }
public bool? Default { get; set; }
public virtual Transmitter Transmitter { get; set; }
}
class Transmitter
{
public int Id { get; set; }
[MaxLength(50)]
public string Description { get; set; }
public virtual ICollection<Calibration> Calibrations { get; set; }
public Calibration GetOfficialCalibration()
{
// This could trigger lazy load
return Calibrations.FirstOrDefault(_ => _.Default == true);
}
}
以上是关于2个表之间的关系 - 一对多和一对一(可空)EF代码优先的主要内容,如果未能解决你的问题,请参考以下文章