Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

One to One and One to Many for the same entity type

I am trying to design the following entity relationship

  • Program
  • Assembly

A Program can have multiple assemblies. One of the assemblies will be a main assembly. Each assembly belongs to one program only.

The classes are modeled as follows:

public class Program
{
    public int Id {get;set;}
    public virtual ProgramAssembly MainAssembly {get;set;}
    public virtual ICollection<ProgramAssembly> Assemblies {get;set;}
}

public class ProgramAssembly
{
   public int Id {get;set;}
   public virtual Program Program {get;set;}
   public int ProgramId {get;set;}
}

I am not specifying anything with the FluentApi (however, I have nothing against it).
With the code above, I get this error:

An error occurred while saving entities that do not expose foreign key properties for their relationships. The EntityEntries property will return null because a single entity cannot be identified as the source of the exception. Handling of exceptions while saving can be made easier by exposing foreign key properties in your entity types. See the InnerException for details.

InnerException: Unable to determine a valid ordering for dependent operations. Dependencies may exist due to foreign key constraints, model requirements, or store-generated values.

I tried changing the ProgramAssembly to the following

public class ProgramAssembly
{
    [ForeignKkey("Program")]
    public int Id {get;set;}
    public virtual Program Program {get;set;}
}

However, then I get this error:

ProgramAssembly_Program_Source: : Multiplicity is not valid in Role 'ProgramAssembly_Program_Source' in relationship 'ProgramAssembly_Program'. Because the Dependent Role refers to the key properties, the upper bound of the multiplicity of the Dependent Role must be '1'.

I also tried a following fluent API approach

modelBuilder.Entity<ProgramAssembly>()
   .HasRequired(a => a.Program)
   .WithMany(p => p.Assemblies);

public class ProgramAssembly
    {        
        public int Id { get; set; }
        public virtual Program Program { get; set; }
        [ForeignKey("Program")] //same error with or without this attribute
        public int ProgramId { get; set; }
   }

Then the error is:

An error occurred while saving entities that do not expose foreign key properties for their relationships. The EntityEntries property will return null because a single entity cannot be identified as the source of the exception. Handling of exceptions while saving can be made easier by exposing foreign key properties in your entity types. See the InnerException for details.' UpdateException: Unable to determine a valid ordering for dependent operations. Dependencies may exist due to foreign key constraints, model requirements, or store-generated values.

How do I allow that relationship without changing the approach to adding 'IsPrimary' attribute on Assembly?

I saw some similar questions on SO, but they were either about EF core, like this one, or suggested significant logic change like this one, or even this one that does not even compile.

like image 857
Bartosz Avatar asked Feb 04 '26 06:02

Bartosz


1 Answers

You need to inform EF how your primary and foreign keys work. You need to add attributes to define your primary keys [Key] and define foreign keys and add attributes to your navigation properties to define the field that is the foreign key.

public class Program
{
    [Key]
    public int Id {get;set;}
    public int MainAssemblyId {get;set;}
    [ForeignKey("MainAssemblyId ")]
    public virtual ProgramAssembly MainAssembly {get;set;}
    public virtual ICollection<ProgramAssembly> Assemblies {get;set;}
}

public class ProgramAssembly
{
   [Key]
   public int Id {get;set;}
   [ForeignKey("ProgramId")]
   public virtual Program Program {get;set;}
   public int ProgramId {get;set;}
}
like image 156
Philip Smith Avatar answered Feb 05 '26 23:02

Philip Smith



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!