One to Zero Relationship not working?

时间:2017-07-17 15:27:14

标签: c# entity-framework code-first one-to-one

I have been trying to establish an optional One-to-One relationship between 2 entities unsuccessfully. I can do it by creating a Unique Constraint on the RTUDEVICE tables DeviceId, but I am trying to do it the "right way" through the Fluent API

What am I doing wrong?

Relationship Explanation:
One DEVICE record may have one-and-only-one record in the RTUDEVICE table.

ENTITIES:
Below are simplified versions of the actual classes...

public partial class Device
{
    public Int Id { get; set; }

    public string DeviceName { get; set; }

    public virtual RTUDevice RTUDevice { get; set; }
}

public partial class RTUDevice
{
    public Int Id { get; set; }

    public int DeviceId { get; set; }

    public bool IsCRMAlarmDevice { get; set; }

    public bool HasCustomRegisters { get; set; }

    public bool HasGasQualityRegisters { get; set; }

    public bool HistoryVerified { get; set; }

    public virtual Device Device { get; set; }
}

MAPPING:
I did many attempts using various online example without success...the failing code is commented-out.

public DeviceMap(DbModelBuilder modelBuilder)
{
    ToTable("Device", "dbo")
        .HasKey(m => m.Id);

    Property(m => m.Id)
        .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
        .IsRequired();

    Property(m => m.DeviceName)
        .IsUnicode(false)
        .HasMaxLength(100)
        .IsRequired()
        .HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("UX_Device_AlternateKey") { IsUnique = true }));

        //modelBuilder.Entity<RTUDevice>()
        //    .HasOptional(e => e.Device)
        //    .WithRequired(e => e.RTUDevice)
        //    .WillCascadeOnDelete(true);
}

public RTUDeviceMap(DbModelBuilder modelBuilder)
{
    ToTable("RTUDevice", "dbo")
        .HasKey(m => m.Id);

    Property(m => m.Id)
        .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
        .IsRequired();

    Property(e => e.DeviceId)
        .IsRequired();

    Property(e => e.IsCRMAlarmDevice )
        .IsRequired();

    Property(e => e.HasCustomRegisters)
        .IsRequired();

    Property(e => e.HasGasQualityRegisters)
        .IsRequired();

    Property(e => e.HistoryVerified)
        .IsRequired();

        // One-to-Zero-or-One relationship
        //modelBuilder.Entity<RTUDevice>()
        //    .HasOptional(e => e.Device)
        //    .WithRequired(e => e.RTUDevice)
        //    .WillCascadeOnDelete(true);

        // One-to-Zero-or-One relationship
        //modelBuilder.Entity<RTUDevice>()
        //    .HasRequired(e => e.Device)
        //    .WithMany()
        //    .HasForeignKey(c => c.DeviceId)
        //    .WillCascadeOnDelete(true);
}

1 个答案:

答案 0 :(得分:0)

你应该在RTUDevice实体中使用Id作为PK(以及FK)并摆脱DeviceId。然后按如下方式定义关系:

modelBuilder.Entity<Device>()
            .HasKey(it => it.Id);

modelBuilder.Entity<RTUDevice>()
            .HasKey(it => it.Id);

modelBuilder.Entity<Device>()
            .HasOptional(it => it.RTUDevice)
            .WithRequired(it => it.Device);

如果需要明确使用DeviceId进行映射,请使用以下命令:

modelBuilder.Entity<Device>()
            .HasOptional(it => it.RTUDevice)
            .WithOptionalPrincipal(it => it.Device)
            .Map(it => it.MapKey("DeviceId"));