0
votes

I am trying to get multiple "units" to have a set of "UnitInfo" assigned but I get the following message from EF when using code first:

One or more validation errors were detected during model generation: Unit_UnitInfo_Source: : Multiplicity is not valid in Role 'Unit_UnitInfo_Source' in relationship 'Unit_UnitInfo'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be ''. SubUnit_UnitInfo_Source: : Multiplicity is not valid in Role 'SubUnit_UnitInfo_Source' in relationship 'SubUnit_UnitInfo'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be ''.

The classes I use looks like this:

public class Unit
{
    public int UnitId { get; set; }
    public string Name { get; set; }
    public List<SubUnit> SubUnits { get; set; }

    [ForeignKey("UnitInfoId")]
    public UnitInfo UnitInfo { get; set; }
}

public class SubUnit
{
    public int SubUnitId { get; set; }
    public string Name { get; set; }

    [ForeignKey("UnitInfoId")]
    public UnitInfo UnitInfo { get; set; }
}

public class UnitInfo
{
    public int UnitInfoId { get; set; }
    public string Function { get; set; }
    public string Location { get; set; }
}

Im sure that it is a simple mistake, I just cant figure it out.

What am I doing wrong?

1
You are free to mark my solution as answer if it helped solving your problem, or do not hesitate to ask more questions about it. - Daniel Leiszen

1 Answers

0
votes

The [ForeignKey()] attribute should refer to either the foreign key, or the navigation property in the same class. So, the UnitInfoId should be a member of the class where you specify the navigation property and the [ForeignKey()] attribute.

The navigation properties should be virtual in order to allow EF to create proxy classes for lazy loading. If you do not use fluent api, you should specify the [Key] attribute for the primary keys. Furthermore, the reference collections should be declared as virtual ICollection members. The architecture you need can be declared as follows:

public class Unit
{
    public Unit()
    {
        SubUnits = new HashSet<SubUnit>();
    }

    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int UnitId { get; set; }
    public string Name { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<SubUnit> SubUnits { get; set; }

    public int UnitInfoId { get; set; }

    [ForeignKey("UnitInfoId")]
    public virtual UnitInfo UnitInfo { get; set; }
}

public class SubUnit
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int SubUnitId { get; set; }
    public int UnitId { get; set; }
    public string Name { get; set; }

    [ForeignKey("UnitId")]
    public virtual Unit ParentUnit { get; set; }

    public int UnitInfoId { get; set; }
    [ForeignKey("UnitInfoId")]
    public UnitInfo UnitInfo { get; set; }
}

public class UnitInfo
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int UnitInfoId { get; set; }
    public string Function { get; set; }
    public string Location { get; set; }
}

However, I would recommend using inheritance, since Unit and SubUnit share the same structure. You can read more about EF code first HERE