【问题标题】:One to Zero Relationship not working?一对零关系不起作用?
【发布时间】:2017-07-18 00:35:31
【问题描述】:

我一直在尝试在 2 个实体之间建立可选的一对一关系,但未成功。我可以通过在 RTUDEVICEDeviceId 上创建唯一约束来做到这一点,但我正在尝试通过 Fluent API 以“正确的方式”进行操作

我做错了什么?

关系说明
一个 DEVICE 记录在 RTUDEVICE 表中可能只有一个记录。

实体:
下面是实际类的简化版本...

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; }
}

制图:
我使用各种在线示例进行了多次尝试,但均未成功...失败的代码已被注释掉。

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);
}

【问题讨论】:

  • RTUDevice 中删除DeviceId 属性并使用MapKey fluent API - 请参阅here

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


【解决方案1】:

您应该只使用 Id 作为 RTUDevice 实体中的 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"));

【讨论】:

  • 这会产生以下错误:无法确定类型“RTUDevice”和“Device”之间关联的主体端。此关联的主体端必须使用关系流式 API 或数据注释显式配置
  • 请尝试使用答案中更新的 .WithOptionalPrincipal(it => it.Device)
  • .WithOptionalPrincipal(it => it.Device) 产生同样的错误
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-10-16
  • 1970-01-01
  • 2016-09-07
  • 2014-05-11
  • 2020-03-14
相关资源
最近更新 更多