Search code examples
c#sqliteentity-framework-coreinterface

How do I create an interface for a conditional one-to-many relation?


I am creating an inventory app for electronic components. There is a package for each component which will change if their assemble technology is on SMD or DIP. Each SMD and DIP has its own options, so I created separate classes and an interface to parent them (to be used in the main resistor model). I want a one-to-many relation so the resistor is searchable from the package.

Models:

public class Resistors
{
    public string Value { get; set; }
    public int Tolerance { get; set; }

    public IResistorPackage Package { get; set; }
    public ResistorAT AssembleTech{ get; set; }
}

The interface has two children:

public class ResistorPackageDIP : IResistorPackage
{
    public int Id { get;  set ; }

    public string RP250mW { get; set; }
    public string RP500mW { get; set; }

    public string RP1W { get; set; }
    public string RP2W { get; set; }
}

public class ResistorPackageSMD : IResistorPackage
{
    public int Id { get; set; }

    public string RP1206 { get; set; }
    public string RP0805 { get; set; }
    public string RP0603 { get; set; }
    public string RP0402 { get; set; }
}

By the "Is a" role they are both packages I want to save based on the IResistorAT property. When someone adds a resistor to the database and chooses SMD, they should (from a combobox) pick a package related to SMD AKA 0603. If they choose DIP they will be suggested the DIP related packages.

If I put them together they might choose a wrong package and assembly technology (resistors don't have DIP of 0805 for example). So I put an interface on the data model since its Id is an integer, however I get this message from Entity Framework Core:

System.InvalidOperationException: 'The property 'Resistors.Package' is of an interface type ('IResistorPackage'). If it is a navigation, manually configure the relationship for this property by casting it to a mapped entity type. Otherwise, ignore the property using the [NotMapped] attribute or 'Ignore' in 'OnModelCreating'.'

This exception happens in the EnsureCreate function on the database. Is there a better way? One of my properties (package) should be changed based on another property (assembly technology), and I rather not have two kinds of resistors since they have much in common.


Solution

  • Here's a suggested starting point for a database design; based on my limited knowledge of your requirements. (A Resistor class is "singular" vs "Resistors" for the table).

    public class Resistor {
       public string Value { get; set; }
       public int Tolerance { get; set; }
    
       public List<int> PackageIds { get; set; }
    
       // ??
       //public ResistorAT AssembleTech { get; set; }  
    }
    
    public enum Technology : byte {
       Undefined = 0,
       //
       SMD,
       DIP
    }  // end enum.
    
    public class ResistorPackage {
    
       public static Dictionary<int, ResistorPackage> Available =
          new Dictionary<int, ResistorPackage>();
    
       public int Id { get; set; }
       public Technology Technology { get; set; }
       public List<string> Resistors { get; set; } = new List<string>();
    
       /// <summary>
       /// 
       /// </summary>
       internal static ResistorPackage FirstOrDefault( string value ) {
    
          foreach ( var package in Available ) {
    
             if ( package.Value.Resistors.Contains( value ) ) {
                return package.Value;
             }
          }  // end for.
    
          return null;
       }
    
    }  // end class.