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

Я создаю приложение для инвентаризации электронных компонентов. Для каждого компонента существует пакет, который будет меняться в зависимости от технологии сборки 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 в базе данных. Есть ли способ лучше? Одно из моих свойств (корпуса) должно быть изменено исходя из другого свойства (технологии сборки), а двух видов резисторов я предпочитаю не иметь, так как они имеют много общего.

Это больше о «дизайне», чем о «интерфейсах». Ваши «пакеты», похоже, имеют «повторяющиеся группы»; которые с точки зрения «нормализации» должны быть «коллекциями» (какими-то). Не хватает только «технического» типа: SMD или DIP. А «Значение» могло бы использовать более описательное имя. Это «ключ», «имя», «номинал резистора»?

Gerry Schmitz 18.07.2024 19:39

Значение @GerrySchmitz примерно 20 или 120 Ом.

S2G 18.07.2024 19:45
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
79
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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
        }
    }
}

Это не решает мою проблему, вы все равно можете предоставить DIP-пакет со значениями SMD.

S2G 18.07.2024 19:40

@S2G Почему вы храните номинальную мощность в разных столбцах? Если вы хотите ввести резисторы в зависимости от их типа (SMD или DIP), вы можете использовать фильтр в пользовательском интерфейсе. Если вы хотите отображать резисторы в зависимости от их типа (SMD или DIP) из базы данных, вы можете использовать фильтры на уровне данных.

Ihdina 19.07.2024 05:01

@S2G Что произойдет, если вы захотите отобразить резистор типа SMD, будет много пустых столбцов. Я предлагаю улучшить вашу таблицу, как указано выше. Это облегчит вам поиск резисторов по нужным критериям.

Ihdina 19.07.2024 05:03
Ответ принят как подходящий

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

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.

Другие вопросы по теме

Похожие вопросы

Код состояния ответа не указывает на успех: BadRequest (400); Подстатус: 0 для базовой вставки CosmosDb
Преобразование поля DateTime в указанный формат в предложенииwhere
Как я могу переписать этот блок if/Else if в более структурированный, сжатый и оптимальный вид. (С#)
Возможная ошибка в выводе предупреждения компилятора C# для проверки допустимости значений NULL
Наследование функций C# и использование возможности повторного использования
Вызов асинхронного метода вызывает отладку
Как выполнить интеграционный тест на конечной точке контроллера API ASP.NET Core, требующей аутентификации и проверки токенов защиты от подделки
Невозможно передать пользовательский атрибут в шаблон Brevo с помощью С#
Как правильно обрабатывать возможные нулевые значения/преобразование нулевых литералов в типы, не допускающие значения NULL, в C#
IAsyncDisposable: следует ли DisposeAsyncCore вызывать Dispose(false)?