How do I properly define the relationship between these classes created by EF Core?

c# entity-framework-core

Question

First of all apologies, this is a rookie question.

I'm trying to write a c# program that connects to an existing database and changes certain values based on user Input. (I know this may sound like a bad idea but we have our reasons…) I decided to use ef core to connect to the database.

I used Scaffold-DbContext to get the database structure into my program. The build succeeded, however whenever I try to run my program I get the following error message:

System.InvalidOperationException: 'The child/dependent side could not be determined for the one-to-one relationship between 'Dad.DadCmu' and 'DadCmu.IddadNavigation'. To identify the child/dependent side of the relationship, configure the foreign key property. If these navigations should not be part of the same relationship configure them without specifying the inverse. See http://go.microsoft.com/fwlink/?LinkId=724062 for more details.'

So the relationship is not well defined I guess. Let's look at the classes then:

    public partial class DadCmu
    {
        public int Iddad { get; set; }
        public byte UnitNo { get; set; }

        public virtual Dad IddadNavigation { get; set; }
    }

So IddadNavigation is of type Dad:

public partial class Dad
    {
        public Dad()
        {
            DadCh = new HashSet<DadCh>();
            DadConnection = new HashSet<DadConnection>();
        }

        public int Iddad { get; set; }
        public string Name { get; set; }
        public int? DadType { get; set; }
        public short? Active { get; set; }
        public DateTime? LastUpdate { get; set; }
        public byte? SynchronizationStatus { get; set; }

        public virtual DadCmu DadCmu { get; set; }
        public virtual DadMasCon DadMasCon { get; set; }
        public virtual DadOpc DadOpc { get; set; }
        public virtual ICollection<DadCh> DadCh { get; set; }
        public virtual ICollection<DadConnection> DadConnection { get; set; }
    }

And their relationship should be defined within OnModelCreating:

protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
        …
        modelBuilder.Entity<DadCmu>(entity =>
            {
                entity.HasKey(e => e.Iddad);

                entity.ToTable("DadCMU");

                entity.Property(e => e.Iddad)
                    .HasColumnName("IDDad")
                    .ValueGeneratedNever();

                entity.HasOne(d => d.IddadNavigation)
                    .WithOne(p => p.DadCmu)
                    .HasForeignKey<DadCmu>(d => d.Iddad)
                    .HasConstraintName("FK_DadCMU_Dad");
            });
        …
        modelBuilder.Entity<Dad>(entity =>
            {
                entity.HasKey(e => e.Iddad);

                entity.Property(e => e.Iddad).HasColumnName("IDDad");

                entity.Property(e => e.LastUpdate).HasColumnType("datetime");
            });
        …
        }

So here within modelBuilder.Entity<DadCmu> it does explicitly mention a foreign key so I'm not quite sure what the problem is? Do I have to do the same within modelBuilder.Entity<Dad>?

What would that code look like?

Or am I misunderstanding the problem entirely?

Is this something that can be done automatically, e.g. with a parameter for scaffold-dbcontext? (My DB has 180 tables and I get the same error for many of them.)

And is this all possible without changing the structure of the db itself?

Thank you so much in Advance! Again, this is my first time working with databases so I apologize if this really obvious.

Edit: Class DadOpc which came up in comments:

    public partial class DadOpc
    {
        public int Iddad { get; set; }
        public string Computer { get; set; }
        public string OpcserviceName { get; set; }
        public float? ScanInterval { get; set; }
        public byte? ServerType { get; set; }
        public byte? UseSecurity { get; set; }

        public virtual Dad IddadNavigation { get; set; }
    }

Edit 2: (regarding jcruz' solution)

Error message:

System.InvalidOperationException: 'The child/dependent side could not be determined for the one-to-one relationship between 'DadMasCon.IddadNavigation' and 'Dad.DadMasCon'. To identify the child/dependent side of the relationship, configure the foreign key property. If these navigations should not be part of the same relationship configure them without specifying the inverse. See http://go.microsoft.com/fwlink/?LinkId=724062 for more details.'

Class Dad:

public partial class Dad
    {
        public Dad()
        {
            DadCh = new HashSet<DadCh>();
            DadConnection = new HashSet<DadConnection>();
        }

        //user added Id-Fields:
        public int DadCmuId { get; set; }
        public int DadOpcId { get; set; }
        public int DadMasConId { get; set; }


        public int Iddad { get; set; }
        public string Name { get; set; }
        public int? DadType { get; set; }
        public short? Active { get; set; }
        public DateTime? LastUpdate { get; set; }
        public byte? SynchronizationStatus { get; set; }

        public virtual DadCmu DadCmu { get; set; }
        public virtual DadMasCon DadMasCon { get; set; }
        public virtual DadOpc DadOpc { get; set; }
        public virtual ICollection<DadCh> DadCh { get; set; }
        public virtual ICollection<DadConnection> DadConnection { get; set; }
    }

Class DadMasCon:

        public DadMasCon()
        {
            DadModbusRegConfig = new HashSet<DadModbusRegConfig>();
        }

        public int Iddad { get; set; }
        public int UnitNo { get; set; }
        public byte? Model { get; set; }
        public DateTime? RefTimeOffset { get; set; }
        public float? TimeoutComm { get; set; }
        public int? Port { get; set; }
        public float? ConnectionInterval { get; set; }
        public byte? ExternalComm { get; set; }
        public string Mvbparameters { get; set; }
        public byte? ModbusBps { get; set; }
        public byte? ModbusParity { get; set; }
        public byte? ModbusStopBits { get; set; }
        public byte? ModbusMode { get; set; }
        public byte? ModbusSlaveAddress { get; set; }
        public byte? CardType0 { get; set; }
        public byte? CardType1 { get; set; }
        public byte? CardType2 { get; set; }
        public byte? CardType3 { get; set; }
        public string LastIp { get; set; }
        public string HiddenParameter { get; set; }
        public int? SerialNo { get; set; }
        public int? LastSequence { get; set; }
        public int? TcppackageErrors { get; set; }
        public byte? UsePrivateFirmware { get; set; }
        public byte? ConfigurationLock { get; set; }
        public byte? IecclientOn { get; set; }
        public string IecclientAddress { get; set; }
        public string IecclientDomain { get; set; }
        public byte? IecsrvOn { get; set; }
        public byte? IecsrvNrOfClents { get; set; }
        public string IecsrvAuthentication { get; set; }
        public string Iecmmsparam { get; set; }
        public float? IecclientPollInterval { get; set; }
        public byte? NtpserverType { get; set; }
        public string Ntpipaddress { get; set; }
        public string IecmmsparamFileName { get; set; }
        public string ModbusTcpaddress { get; set; }
        public int? ModbusTcpportNr { get; set; }
        public byte? ModbusByteOrder { get; set; }
        public byte? ModbusClientValueType { get; set; }
        public string Macaddress { get; set; }
        public byte? MonitorInitiate { get; set; }

        public virtual Dad IddadNavigation { get; set; }
        public virtual ICollection<DadModbusRegConfig> DadModbusRegConfig { get; set; }
    }

OnModelCreating:

modelBuilder.Entity<DadMasCon>(entity =>
            {
                entity.HasKey(e => e.Iddad)
                    .HasName("PK_DadMasCon16");

                entity.Property(e => e.Iddad)
                    .HasColumnName("IDDad")
                    .ValueGeneratedNever();

                entity.Property(e => e.IecclientAddress).HasColumnName("IECClientAddress");

                entity.Property(e => e.IecclientDomain).HasColumnName("IECClientDomain");

                entity.Property(e => e.IecclientOn).HasColumnName("IECClientOn");

                entity.Property(e => e.IecclientPollInterval).HasColumnName("IECClientPollInterval");

                entity.Property(e => e.Iecmmsparam).HasColumnName("IECMMSParam");

                entity.Property(e => e.IecmmsparamFileName).HasColumnName("IECMMSParamFileName");

                entity.Property(e => e.IecsrvAuthentication).HasColumnName("IECSrvAuthentication");

                entity.Property(e => e.IecsrvNrOfClents).HasColumnName("IECSrvNrOfClents");

                entity.Property(e => e.IecsrvOn).HasColumnName("IECSrvOn");

                entity.Property(e => e.Macaddress).HasColumnName("MACAddress");

                entity.Property(e => e.ModbusTcpaddress)
                    .HasColumnName("ModbusTCPAddress")
                    .HasMaxLength(50);

                entity.Property(e => e.ModbusTcpportNr).HasColumnName("ModbusTCPPortNr");

                entity.Property(e => e.Mvbparameters).HasColumnName("MVBParameters");

                entity.Property(e => e.Ntpipaddress).HasColumnName("NTPIPAddress");

                entity.Property(e => e.NtpserverType).HasColumnName("NTPServerType");

                entity.Property(e => e.RefTimeOffset).HasColumnType("datetime");

                entity.Property(e => e.TcppackageErrors).HasColumnName("TCPPackageErrors");

                //user generated:
                entity.HasOne(d => d.IddadNavigation)
                    .WithOne(p => p.DadMasCon)
                    .HasForeignKey<Dad>(d => d.DadMasConId);

                //original:
                //entity.HasOne(d => d.IddadNavigation)
                //    .WithOne(p => p.DadMasCon)
                //    .HasForeignKey<DadMasCon>(d => d.Iddad)
                //    .HasConstraintName("FK_DadMasCon_Dad");
            });
1
4
1/22/2020 4:54:37 PM

Popular Answer

Since you are trying to define a one-to-one relationship you need to explicitly define the back reference id on your Dad model to ensure it maps to a single DadCmu record.

public partial class Dad
{
    public int DadCmuId { get; set; }
    public virtual DadCmu DadCmu { get; set; }
}

You can then configure this using the fluent API like this:

modelBuilder.Entity<DadCmu>(entity =>
{
    entity.HasOne(d => d.IddadNavigation)
          .WithOne(p => p.DadCmu)
          .HasForeignKey<Dad>(d => d.DadCmuId);
});

HTH

1
1/22/2020 3:11:45 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow