7.8 KiB
Data Layer
Part of
Nop.Plugin.Misc.FruitBankPlugin. SeeREADME.mdfor project overview. For entity model seedocs/DOMAIN_MODEL.md. For measurement workflows seedocs/MEASUREMENT.md.
DbContext Classes
FruitBankDbContext
Inherits MgDbContextBase (from Mango.Nop.Data). Main data context for orders, shipping, partners, and files.
Implements interfaces: IOrderDtoDbSet, IOrderItemDtoDbSet, IPartnerDbSet, IShippingDbSet, IShippingDocumentDbSet, IShippingItemDbSet, IShippingItemPalletDbSet, IOrderItemPalletDbSet, IShippingDocumentToFilesDbSet, IFilesDbSet
DbSet properties:
| DbSet | Entity | Table |
|---|---|---|
OrderDtos |
OrderDto | Order |
OrderItemDtos |
OrderItemDto | OrderItem |
OrderItemPallets |
OrderItemPallet | fbOrderItemPallet |
Partners |
Partner | fbPartner |
Shippings |
Shipping | fbShipping |
ShippingDocuments |
ShippingDocument | fbShippingDocument |
ShippingItems |
ShippingItem | fbShippingItem |
ShippingItemPallets |
ShippingItemPallet | fbShippingItemPallet |
Files |
Files | fbFiles |
ShippingDocumentToFiles |
ShippingDocumentToFiles | fbShippingDocumentToFiles |
ProductDtos |
ProductDto | Product |
GenericAttributeDtos |
GenericAttributeDto | GenericAttribute |
StockQuantityHistoryDtos |
StockQuantityHistoryDto | StockQuantityHistory |
Customers |
Customer | Customer |
CustomerRoles |
CustomerRole | CustomerRole |
Key methods:
| Method | Purpose |
|---|---|
AddShippingItemAsync() |
Creates item, copies IsMeasurable from ProductDto |
UpdateShippingItemAsync() |
Complex: updates measuring values, handles stock/weight changes, manages product transitions |
SetupShippingItemMeasuringValues() |
Recalculates totals from child pallets |
AddShippingItemPalletAsync() / UpdateShippingItemPalletAsync() |
Pallet CRUD with cascade to parent ShippingItem |
StartMeasuringAsync() |
Sets MeasurementOwnerId GenericAttribute, updates order status |
SetOrderStatusToCompleteAsync() |
Validates pallets, updates stock, sets RevisorId, publishes event |
DeleteOrderItemConstraintsAsync() |
Cleanup when order items deleted |
UpdateStockQuantityAndWeightAsync() |
Updates Product.StockQuantity + NetWeight, creates history entry |
DeleteShippingSafeAsync() |
Transactional cascade delete of shipping + children |
DeleteShippingDocumentSafeAsync() |
Transactional cascade delete of document + children |
GetCustomersBySystemRoleName() |
LINQ query for role-based customer lookup |
All state-changing operations wrapped in TransactionSafeAsync() for ACID compliance.
StockTakingDbContext
Inherits MgDbContextBase. Dedicated context for inventory sessions.
DbSet properties:
| DbSet | Entity |
|---|---|
ProductDtos |
ProductDto |
OrderItemDtos |
OrderItemDto |
StockTakings |
StockTaking |
StockTakingItems |
StockTakingItem |
StockTakingItemPallets |
StockTakingItemPallet |
StockQuantityHistories |
StockQuantityHistory |
GenericAttributes |
GenericAttribute |
Key methods:
| Method | Purpose |
|---|---|
CloseStockTaking() |
Validates all measured, updates stock/weight per item, marks closed |
AddStockTakingItemPallet() / UpdateStockTakingItemPallet() |
Pallet CRUD with measured values refresh |
RefreshStockTakingItemMeasuredValuesFromPallets() |
Sums quantities/weights from pallets |
DbTable Repositories
Each entity has a *DbTable class inheriting MgDbTableBase<T> (from Mango.Nop.Data). Located in Domains/DataLayer/.
ShippingDbTable
| Method | Purpose |
|---|---|
GetAll() |
All shippings ordered by ShippingDate |
GetAll(bool loadRelations) |
Eager loads full graph: Documents → Items → Pallets + Pallet type + ProductDto + GenericAttributes |
GetAllNotMeasured() |
Filters for incomplete/recent shipments |
GetByIdAsync(bool loadRelations) |
Single with optional eager loading |
OnUpdate() |
Hook: sets MeasuredDate when IsAllMeasured becomes true |
OrderDtoDbTable
| Method | Purpose |
|---|---|
GetAll(bool loadRelations) |
Eager loads: GenericAttributes, Customer, OrderNotes, OrderItemDtos (with ProductDto, GenericAttributes, OrderItemPallets) |
GetByIdAsync(bool loadRelations) |
Single order with optional relations |
GetAllByOrderStatus() |
Status-filtered query |
GetAllForMeasuring(DateTime fromDate) |
Unpaid, not cancelled, with DateOfReceipt >= fromDate |
GetAllByProductId() / GetAllByProductIds() |
Product-filtered queries |
GetAllByIds() |
Batch retrieval |
Other DbTable classes
| Class | Entity | Key behaviors |
|---|---|---|
ProductDtoDbTable |
ProductDto | GetAll with GenericAttributes |
PartnerDbTable |
Partner | Standard CRUD |
ShippingDocumentDbTable |
ShippingDocument | GetAll with items, files, partner |
ShippingItemDbTable |
ShippingItem | GetAll with pallets |
ShippingItemPalletDbTable |
ShippingItemPallet | Standard CRUD |
OrderItemDtoDbTable |
OrderItemDto | GetAll with pallets, product |
OrderItemPalletDbTable |
OrderItemPallet | Standard CRUD |
FilesDbTable |
Files | Standard CRUD |
ShippingDocumentToFilesDbTable |
ShippingDocumentToFiles | Standard CRUD |
StockTakingDbTable |
StockTaking | GetAll with items, pallets |
StockTakingItemDbTable |
StockTakingItem | GetAll with pallets |
StockTakingItemPalletDbTable |
StockTakingItemPallet | Standard CRUD |
StockQuantityHistoryDtoDbTable |
StockQuantityHistoryDto | Filtered by date range |
Repository Interfaces
Located in Domains/DataLayer/Interfaces/. Each interface (e.g., IShippingDbSet, IOrderDtoDbSet) declares the DbSet property that the DbContext must implement. This allows DbTable classes to accept any context that provides the required DbSet.
Entity Mapping
Mapping/Builders/PluginBuilder.cs— EF Core Fluent API entity configuration for plugin-owned tables (fb* prefix)Mapping/NameCompatibility.cs— Table name mapping for nopCommerce compatibilityMigrations/SchemaMigration.cs— FluentMigrator schema setup forCustomTablebase entity
FruitBankEventConsumer
Located in Domains/EventConsumers/. Extends MgEventConsumerBase (from Mango.Nop.Services). Handles entity lifecycle events for cascading updates.
Product events:
| Event | Action |
|---|---|
EntityInsertedEvent<Product> |
Saves custom attributes (IsMeasurable, NetWeight, Tare, AverageWeight, AverageWeightTreshold, IncomingQuantity) |
EntityUpdatedEvent<Product> |
Updates custom attributes, syncs IsMeasurable/Tare changes to existing ShippingItems |
Shipping cascade events:
| Event | Action |
|---|---|
EntityDeletedEvent<ShippingItemPallet> |
Refreshes parent ShippingItem measuring values |
EntityInsertedEvent/UpdatedEvent<ShippingItem> |
Rechecks ShippingDocument.IsAllMeasured |
EntityInsertedEvent/UpdatedEvent<ShippingDocument> |
Rechecks Shipping.IsAllMeasured |
EntityDeletedEvent<Shipping> |
Cascade deletes child documents |
EntityDeletedEvent<ShippingDocument> |
Cascade deletes child items |
EntityDeletedEvent<ShippingItem> |
Cascade deletes child pallets |
Order events:
| Event | Action |
|---|---|
EntityDeletedEvent<OrderItem> |
Cleanup via MeasurementService.DeleteOrderItemConstraintsAsync() |
EntityInsertedEvent/UpdatedEvent<OrderItem> |
Post-process via MeasurementService.OrderItemInsertedOrUpdatedPostProcess() |
Eager Loading Pattern
DbTable GetAll(bool loadRelations = true) uses LoadWith() chains to eagerly load entity graphs. Example for OrderDtoDbTable:
OrderDto
→ GenericAttributes
→ Customer
→ OrderNotes
→ OrderItemDtos
→ ProductDto → GenericAttributes
→ GenericAttributes
→ OrderItemPallets
This avoids N+1 queries when transferring full entity graphs to FruitBankHybridApp via SignalR.