Как создать интерфейс для условного отношения «один ко многим»?

Я создаю приложение для инвентаризации электронных компонентов. Для каждого компонента существует пакет, который будет меняться в зависимости от технологии сборки SMD или DIP. У каждого SMD и DIP есть свои параметры, поэтому я создал отдельные классы и родительский интерфейс (для использования в модели основного резистора). Мне нужно отношение «один ко многим», чтобы резистор можно было найти в пакете.

Модели:

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

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

У интерфейса есть два дочерних элемента:

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

По роли «Является» оба пакета являются пакетами, которые я хочу сохранить на основе свойства IResistorAT. Когда кто-то добавляет резистор в базу данных и выбирает SMD, он должен (из поля со списком) выбрать пакет, относящийся к SMD AKA 0603. Если он выберет DIP, ему будут предложены пакеты, связанные с DIP.

Если я соберу их вместе, они могут выбрать неправильную упаковку и технологию сборки (например, резисторы не имеют DIP 0805). Поэтому я поместил интерфейс в модель данных, поскольку его идентификатор является целым числом, однако я получаю это сообщение от Entity Framework Core:

System.InvalidOperationException: «Свойство Resistors.Package имеет тип интерфейса («IResistorPackage»). Если это навигация, вручную настройте связь для этого свойства, приведя его к сопоставленному типу сущности. В противном случае игнорируйте свойство, используя атрибут [NotMapped] или «Игнорировать» в «OnModelCreating».

Это исключение происходит в функции EnsureCreate в базе данных. Есть ли способ лучше? Одно из моих свойств (корпуса) должно быть изменено исходя из другого свойства (технологии сборки), а двух видов резисторов я предпочитаю не иметь, так как они имеют много общего.

🤔 А знаете ли вы, что...
C# поддерживает атрибуты, которые позволяют добавлять метаданные к коду.


79
2

Ответы:

Создайте простую базу данных SQLite, как показано ниже.

// Create a table named Resistors to store resistor data (Sql lite).
CREATE TABLE Resistors (
    Id INTEGER PRIMARY KEY AUTOINCREMENT,
    Value TEXT NOT NULL,
    Tolerance REAL NOT NULL,
    Type INTEGER NOT NULL,
    PowerRating REAL NOT NULL,
    PackageType TEXT NOT NUL,
    -- Add more columns as needed
);


// Ensure you have the necessary packages installed in your project (VS 2022):
dotnet add package Microsoft.EntityFrameworkCore.Sqlite
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.EntityFrameworkCore.Tools

public enum ResistorType
{
    NONE, // 0
    SMD,  // 1
    DIP   // 2
    // etc
}

// Create a Resistor class that represents your resistor entity:
public class Resistor
{
    public int Id { get; set; }             // Primary key
    public string Value { get; set; }       // Value of the resistor (e.g., "10K")
    public double Tolerance { get; set; }   // Tolerance percentage (e.g., 5 for ±5%)
    public int Type { get; set; }        // Type of resistor (NONE=0, SMD=1, DIP=2, etc.)
    public double PowerRating { get; set; } // PowerRating of the resistor (e.g., 250mW, 1W, 2W, etc)
    public string PackageType { get; set; } // e.g., "0402", "0603", "0805", "DIP-8", "DIP-16"
}

// Set up your ResistorDbContext to define the database context and specify the Resistors table:
public class ResistorDbContext : DbContext
{
    public DbSet<Resistor> Resistors { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlite("Data Source=resistors.db"); // SQLite connection string
    }
}

// Generate migrations and apply them to create the database schema:
dotnet ef migrations add InitialCreate
dotnet ef database update

// Create a service or repository class (ResistorService in this example) to encapsulate CRUD operations:
public class ResistorService
{
    private readonly ResistorDbContext _context;

    public ResistorService(ResistorDbContext context)
    {
        _context = context;
    }

    // Create operation
    public void AddResistor(Resistor resistor)
    {
        _context.Resistors.Add(resistor);
        _context.SaveChanges();
    }

    // Read operations
    public List<Resistor> GetAllResistors()
    {
        return _context.Resistors.ToList();
    }

    public Resistor GetResistorById(int id)
    {
        return _context.Resistors.Find(id);
    }

    // Update operation
    public void UpdateResistor(Resistor resistor)
    {
        _context.Resistors.Update(resistor);
        _context.SaveChanges();
    }

    // Delete operation
    public void DeleteResistor(int id)
    {
        var resistor = _context.Resistors.Find(id);
        if (resistor != null)
        {
            _context.Resistors.Remove(resistor);
            _context.SaveChanges();
        }
    }
}

// Here’s how you might use the ResistorService in your application:
class Program
{
    static void Main(string[] args)
    {
        using (var context = new ResistorDbContext())
        {
            var service = new ResistorService(context);

            // Create SMD resistor
            var smdResistor = new Resistor
            {
                Value = "10K",
                Tolerance = 1,
                Type = (int)ResistorType.SMD
                PowerRating = 0.25
                PackageType = "0402"
            };
            service.AddResistor(smdResistor);

            // Create DIP resistor
            var dipResistor = new Resistor
            {
                Value = "10K",
                Tolerance = 5,
                Type = (int)ResistorType.DIP
                PowerRating = 1
                PackageType = "DIP-8"
            };
            service.AddResistor(dipResistor);

            // Read all
            var allResistors = service.GetAllResistors();
            foreach (var resistor in allResistors)
            {
                Console.WriteLine($"ID: {resistor.Id}, Value: {resistor.Value}, Tolerance: {resistor.Tolerance}, Type: {resistor.Type}, PowerRating: {resistor.PowerRating}, PackageType: {resistor.PackageType}");
            }

            // Update
            var resistorToUpdate = service.GetResistorById(1);
            if (resistorToUpdate != null)
            {
                resistorToUpdate.Tolerance = 1; // Change tolerance to 1%
                service.UpdateResistor(resistorToUpdate);
            }

            // Delete
            service.DeleteResistor(2); // Assuming resistor with ID 2 exists and is to be deleted
        }
    }
}

Решено

Вот рекомендуемая отправная точка для проектирования базы данных; на основе моего ограниченного знания ваших требований. (Класс резистора в таблице является «единственным» по сравнению с «Резисторами»).

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.