Compare commits

...

2 Commits

Author SHA1 Message Date
6ae8e7b62c Update migration 2024-04-30 23:14:08 +04:00
48e52db40e fix ForeignKey constraints in DB models 2024-04-30 23:03:49 +04:00
6 changed files with 679 additions and 14 deletions

View File

@ -0,0 +1,524 @@
// <auto-generated />
using System;
using ComputerShopDatabaseImplement;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace ComputerShopDatabaseImplement.Migrations
{
[DbContext(typeof(ComputerShopDatabase))]
[Migration("20240430190807_ForeignKey-fix")]
partial class ForeignKeyfix
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.18")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Assembly", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("AssemblyName")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Category")
.IsRequired()
.HasColumnType("text");
b.Property<double>("Cost")
.HasColumnType("double precision");
b.Property<int>("UserId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("Assemblies");
});
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.AssemblyComponent", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("AssemblyId")
.HasColumnType("integer");
b.Property<int>("ComponentId")
.HasColumnType("integer");
b.Property<int>("Count")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("AssemblyId");
b.HasIndex("ComponentId");
b.ToTable("AssemblyComponents");
});
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Component", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ComponentName")
.IsRequired()
.HasColumnType("text");
b.Property<double>("Cost")
.HasColumnType("double precision");
b.Property<int>("UserId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("Components");
});
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Order", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<DateTime>("DateCreate")
.HasColumnType("timestamp without time zone");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<double>("Sum")
.HasColumnType("double precision");
b.Property<int>("UserId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("Orders");
});
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Product", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<double>("Cost")
.HasColumnType("double precision");
b.Property<string>("ProductName")
.IsRequired()
.HasColumnType("text");
b.Property<int?>("ShipmentId")
.HasColumnType("integer");
b.Property<int>("UserId")
.HasColumnType("integer");
b.Property<int>("Warranty")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("ShipmentId");
b.HasIndex("UserId");
b.ToTable("Products");
});
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.ProductComponent", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("ComponentId")
.HasColumnType("integer");
b.Property<int>("Count")
.HasColumnType("integer");
b.Property<int>("ProductId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("ComponentId");
b.HasIndex("ProductId");
b.ToTable("ProductComponents");
});
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Request", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int?>("AssemblyId")
.HasColumnType("integer");
b.Property<string>("ClientFIO")
.IsRequired()
.HasColumnType("text");
b.Property<DateTime>("DateRequest")
.HasColumnType("timestamp without time zone");
b.Property<int>("UserId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("AssemblyId");
b.HasIndex("UserId");
b.ToTable("Requests");
});
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.RequestOrder", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("OrderId")
.HasColumnType("integer");
b.Property<int>("RequestId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("OrderId");
b.HasIndex("RequestId");
b.ToTable("RequestOrders");
});
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Shipment", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<DateTime>("DateShipment")
.HasColumnType("timestamp without time zone");
b.Property<string>("ProviderName")
.IsRequired()
.HasColumnType("text");
b.Property<int>("UserId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("Shipments");
});
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.ShipmentOrder", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("OrderId")
.HasColumnType("integer");
b.Property<int>("ShipmentId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("OrderId");
b.HasIndex("ShipmentId");
b.ToTable("ShipmentOrders");
});
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Email")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Login")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("text");
b.Property<int>("Role")
.HasColumnType("integer");
b.HasKey("Id");
b.ToTable("Users");
});
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Assembly", b =>
{
b.HasOne("ComputerShopDatabaseImplement.Models.User", null)
.WithMany("Assemblies")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.AssemblyComponent", b =>
{
b.HasOne("ComputerShopDatabaseImplement.Models.Assembly", "Assembly")
.WithMany("Components")
.HasForeignKey("AssemblyId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("ComputerShopDatabaseImplement.Models.Component", "Component")
.WithMany("AssemblyComponents")
.HasForeignKey("ComponentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Assembly");
b.Navigation("Component");
});
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Component", b =>
{
b.HasOne("ComputerShopDatabaseImplement.Models.User", null)
.WithMany("Components")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Order", b =>
{
b.HasOne("ComputerShopDatabaseImplement.Models.User", null)
.WithMany("Orders")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Product", b =>
{
b.HasOne("ComputerShopDatabaseImplement.Models.Shipment", "Shipment")
.WithMany("Products")
.HasForeignKey("ShipmentId");
b.HasOne("ComputerShopDatabaseImplement.Models.User", null)
.WithMany("Proucts")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Shipment");
});
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.ProductComponent", b =>
{
b.HasOne("ComputerShopDatabaseImplement.Models.Component", "Component")
.WithMany("ProductComponents")
.HasForeignKey("ComponentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("ComputerShopDatabaseImplement.Models.Product", "Product")
.WithMany("Components")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Component");
b.Navigation("Product");
});
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Request", b =>
{
b.HasOne("ComputerShopDatabaseImplement.Models.Assembly", "Assembly")
.WithMany("Requests")
.HasForeignKey("AssemblyId");
b.HasOne("ComputerShopDatabaseImplement.Models.User", "User")
.WithMany("Requests")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Assembly");
b.Navigation("User");
});
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.RequestOrder", b =>
{
b.HasOne("ComputerShopDatabaseImplement.Models.Order", "Order")
.WithMany("Requests")
.HasForeignKey("OrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("ComputerShopDatabaseImplement.Models.Request", "Request")
.WithMany("Orders")
.HasForeignKey("RequestId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Order");
b.Navigation("Request");
});
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Shipment", b =>
{
b.HasOne("ComputerShopDatabaseImplement.Models.User", "User")
.WithMany("Shipments")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.ShipmentOrder", b =>
{
b.HasOne("ComputerShopDatabaseImplement.Models.Order", "Order")
.WithMany("Shipments")
.HasForeignKey("OrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("ComputerShopDatabaseImplement.Models.Shipment", "Shipment")
.WithMany("Orders")
.HasForeignKey("ShipmentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Order");
b.Navigation("Shipment");
});
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Assembly", b =>
{
b.Navigation("Components");
b.Navigation("Requests");
});
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Component", b =>
{
b.Navigation("AssemblyComponents");
b.Navigation("ProductComponents");
});
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Order", b =>
{
b.Navigation("Requests");
b.Navigation("Shipments");
});
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Product", b =>
{
b.Navigation("Components");
});
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Request", b =>
{
b.Navigation("Orders");
});
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Shipment", b =>
{
b.Navigation("Orders");
b.Navigation("Products");
});
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.User", b =>
{
b.Navigation("Assemblies");
b.Navigation("Components");
b.Navigation("Orders");
b.Navigation("Proucts");
b.Navigation("Requests");
b.Navigation("Shipments");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,128 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ComputerShopDatabaseImplement.Migrations
{
/// <inheritdoc />
public partial class ForeignKeyfix : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_AssemblyComponents_Assemblies_ComponentId",
table: "AssemblyComponents");
migrationBuilder.DropForeignKey(
name: "FK_ProductComponents_Components_ComponentId1",
table: "ProductComponents");
migrationBuilder.DropForeignKey(
name: "FK_ProductComponents_Products_ComponentId",
table: "ProductComponents");
migrationBuilder.DropIndex(
name: "IX_ProductComponents_ComponentId1",
table: "ProductComponents");
migrationBuilder.DropColumn(
name: "ComponentId1",
table: "ProductComponents");
migrationBuilder.CreateIndex(
name: "IX_ProductComponents_ProductId",
table: "ProductComponents",
column: "ProductId");
migrationBuilder.CreateIndex(
name: "IX_AssemblyComponents_AssemblyId",
table: "AssemblyComponents",
column: "AssemblyId");
migrationBuilder.AddForeignKey(
name: "FK_AssemblyComponents_Assemblies_AssemblyId",
table: "AssemblyComponents",
column: "AssemblyId",
principalTable: "Assemblies",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_ProductComponents_Components_ComponentId",
table: "ProductComponents",
column: "ComponentId",
principalTable: "Components",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_ProductComponents_Products_ProductId",
table: "ProductComponents",
column: "ProductId",
principalTable: "Products",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_AssemblyComponents_Assemblies_AssemblyId",
table: "AssemblyComponents");
migrationBuilder.DropForeignKey(
name: "FK_ProductComponents_Components_ComponentId",
table: "ProductComponents");
migrationBuilder.DropForeignKey(
name: "FK_ProductComponents_Products_ProductId",
table: "ProductComponents");
migrationBuilder.DropIndex(
name: "IX_ProductComponents_ProductId",
table: "ProductComponents");
migrationBuilder.DropIndex(
name: "IX_AssemblyComponents_AssemblyId",
table: "AssemblyComponents");
migrationBuilder.AddColumn<int>(
name: "ComponentId1",
table: "ProductComponents",
type: "integer",
nullable: false,
defaultValue: 0);
migrationBuilder.CreateIndex(
name: "IX_ProductComponents_ComponentId1",
table: "ProductComponents",
column: "ComponentId1");
migrationBuilder.AddForeignKey(
name: "FK_AssemblyComponents_Assemblies_ComponentId",
table: "AssemblyComponents",
column: "ComponentId",
principalTable: "Assemblies",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_ProductComponents_Components_ComponentId1",
table: "ProductComponents",
column: "ComponentId1",
principalTable: "Components",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_ProductComponents_Products_ComponentId",
table: "ProductComponents",
column: "ComponentId",
principalTable: "Products",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
}
}

View File

@ -70,6 +70,8 @@ namespace ComputerShopDatabaseImplement.Migrations
b.HasKey("Id"); b.HasKey("Id");
b.HasIndex("AssemblyId");
b.HasIndex("ComponentId"); b.HasIndex("ComponentId");
b.ToTable("AssemblyComponents"); b.ToTable("AssemblyComponents");
@ -171,9 +173,6 @@ namespace ComputerShopDatabaseImplement.Migrations
b.Property<int>("ComponentId") b.Property<int>("ComponentId")
.HasColumnType("integer"); .HasColumnType("integer");
b.Property<int>("ComponentId1")
.HasColumnType("integer");
b.Property<int>("Count") b.Property<int>("Count")
.HasColumnType("integer"); .HasColumnType("integer");
@ -184,7 +183,7 @@ namespace ComputerShopDatabaseImplement.Migrations
b.HasIndex("ComponentId"); b.HasIndex("ComponentId");
b.HasIndex("ComponentId1"); b.HasIndex("ProductId");
b.ToTable("ProductComponents"); b.ToTable("ProductComponents");
}); });
@ -331,7 +330,7 @@ namespace ComputerShopDatabaseImplement.Migrations
{ {
b.HasOne("ComputerShopDatabaseImplement.Models.Assembly", "Assembly") b.HasOne("ComputerShopDatabaseImplement.Models.Assembly", "Assembly")
.WithMany("Components") .WithMany("Components")
.HasForeignKey("ComponentId") .HasForeignKey("AssemblyId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
@ -366,7 +365,7 @@ namespace ComputerShopDatabaseImplement.Migrations
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Product", b => modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Product", b =>
{ {
b.HasOne("ComputerShopDatabaseImplement.Models.Shipment", null) b.HasOne("ComputerShopDatabaseImplement.Models.Shipment", "Shipment")
.WithMany("Products") .WithMany("Products")
.HasForeignKey("ShipmentId"); .HasForeignKey("ShipmentId");
@ -375,19 +374,21 @@ namespace ComputerShopDatabaseImplement.Migrations
.HasForeignKey("UserId") .HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
b.Navigation("Shipment");
}); });
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.ProductComponent", b => modelBuilder.Entity("ComputerShopDatabaseImplement.Models.ProductComponent", b =>
{ {
b.HasOne("ComputerShopDatabaseImplement.Models.Product", "Product") b.HasOne("ComputerShopDatabaseImplement.Models.Component", "Component")
.WithMany("Components") .WithMany("ProductComponents")
.HasForeignKey("ComponentId") .HasForeignKey("ComponentId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
b.HasOne("ComputerShopDatabaseImplement.Models.Component", "Component") b.HasOne("ComputerShopDatabaseImplement.Models.Product", "Product")
.WithMany() .WithMany("Components")
.HasForeignKey("ComponentId1") .HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
@ -399,7 +400,7 @@ namespace ComputerShopDatabaseImplement.Migrations
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Request", b => modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Request", b =>
{ {
b.HasOne("ComputerShopDatabaseImplement.Models.Assembly", "Assembly") b.HasOne("ComputerShopDatabaseImplement.Models.Assembly", "Assembly")
.WithMany() .WithMany("Requests")
.HasForeignKey("AssemblyId"); .HasForeignKey("AssemblyId");
b.HasOne("ComputerShopDatabaseImplement.Models.User", "User") b.HasOne("ComputerShopDatabaseImplement.Models.User", "User")
@ -465,11 +466,15 @@ namespace ComputerShopDatabaseImplement.Migrations
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Assembly", b => modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Assembly", b =>
{ {
b.Navigation("Components"); b.Navigation("Components");
b.Navigation("Requests");
}); });
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Component", b => modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Component", b =>
{ {
b.Navigation("AssemblyComponents"); b.Navigation("AssemblyComponents");
b.Navigation("ProductComponents");
}); });
modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Order", b => modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Order", b =>

View File

@ -21,7 +21,10 @@ namespace ComputerShopDatabaseImplement.Models
[Required] [Required]
public string Category { get; private set; } = string.Empty; public string Category { get; private set; } = string.Empty;
[ForeignKey("ComponentId")] [ForeignKey("AssemblyId")]
public virtual List<Request> Requests { get; set; } = new();
[ForeignKey("AssemblyId")]
public virtual List<AssemblyComponent> Components { get; set; } = new(); public virtual List<AssemblyComponent> Components { get; set; } = new();
private Dictionary<int, (IComponentModel, int)>? _assemblyComponents; private Dictionary<int, (IComponentModel, int)>? _assemblyComponents;

View File

@ -19,6 +19,9 @@ namespace ComputerShopDatabaseImplement.Models
[Required] [Required]
public double Cost { get; private set; } public double Cost { get; private set; }
[ForeignKey("ComponentId")]
public virtual List<ProductComponent> ProductComponents { get; set; } = new();
[ForeignKey("ComponentId")] [ForeignKey("ComponentId")]
public virtual List<AssemblyComponent> AssemblyComponents { get; set; } = new(); public virtual List<AssemblyComponent> AssemblyComponents { get; set; } = new();

View File

@ -23,7 +23,9 @@ namespace ComputerShopDatabaseImplement.Models
public int? ShipmentId { get; set; } public int? ShipmentId { get; set; }
[ForeignKey("ComponentId")] public virtual Shipment? Shipment { get; set; }
[ForeignKey("ProductId")]
public virtual List<ProductComponent> Components { get; set; } = new(); public virtual List<ProductComponent> Components { get; set; } = new();
private Dictionary<int, (IComponentModel, int)>? _productComponents; private Dictionary<int, (IComponentModel, int)>? _productComponents;