Tutorial — aggiungere un campo a reg.companies
Esempio reg-specifico del pattern generale di estensione CRUD. Per i
passi generali del generatore (sync DB, invocazione MCP, rigenerazione,
commit), vedi il tutorial base nel dominio inv:
Aggiungere un campo su inv.invoices.
Questa pagina mostra solo le specificità applicabili a reg.companies.
🎯 Cosa fa
Tutorial sull'aggiunta di un campo noteInterne (note riservate al
personale amministrativo, non visibili al cliente) alla tabella
reg.companies. Copre le particolarità di un'entità con
AddressFormatter, cascade ATECO e hook QueryModifier.
⚠️ Prerequisiti
Stessi del tutorial inv:
- Ambiente sviluppo con
TrainingHub.Databaseapribile - DB locale collegato
- MCP
3sd-generatorconfigurato - Branch dedicato
👣 Passi
1. Modifica reg.companies nel progetto DB
File: TrainingHub.Database/reg/Tables/companies.sql.
Aggiungi la colonna dopo le altre colonne testo e gli extended properties corrispondenti:
CREATE TABLE [reg].[companies] (
[id] UNIQUEIDENTIFIER CONSTRAINT [DEFAULT_companies_id] DEFAULT (newid()) NOT NULL,
-- ... righe esistenti ...
[notes] NVARCHAR (1024) NULL,
[noteInterne] NVARCHAR (MAX) NULL,
-- ... righe esistenti + constraint ...
);
GO
EXECUTE sp_addextendedproperty @name = N'MS_Description',
@value = N'Note interne riservate al personale amministrativo (non visibili al cliente)',
@level0type = N'SCHEMA', @level0name = N'reg',
@level1type = N'TABLE', @level1name = N'companies',
@level2type = N'COLUMN', @level2name = N'noteInterne';
GO
Note reg-specifiche:
NVARCHAR(MAX)per contenuto lungo. Non appesantisce la riga a meno che non sia popolato (SQL Server tiene MAX off-row se serve).- Evita di piazzare il campo fra le colonne indirizzo: l'
AddressFormatterdel form si aspetta un layout contiguo di campi indirizzo.
2. Sincronizza il DB locale
Uguale al tutorial inv: sqlpackage /Action:Publish o Visual Studio
Publish.
3. Verifica conf.json
File: TrainingHub.BackOffice/Components/CRUD/reg/_conf/companies.dxgrid.conf.json.
Per default il generatore include il nuovo campo in grid e form. Per
noteInterne probabilmente vuoi:
- Nascondere in grid di default (testo lungo, ingombrante in lista)
- Mostrare in form (editabile)
- Posizionare nella sezione delle note esistenti nel
FormOrder
{
"Columns": {
"noteInterne": {
"Visible": false,
"FormInsertVisibility": "editable",
"FormUpdateVisibility": "editable"
}
},
"FormOrder": [
// ... altri campi ...
"notes",
"noteInterne"
]
}
4. Esegui rigenerazione CRUD
Invoca il tool MCP:
mcp__3sd-generator__generator_runper l'entitàcompanies
File che devono cambiare:
TrainingHub.BackOffice/Components/CRUD/reg/Company.razor
TrainingHub.BackOffice/Components/CRUD/reg/Company.razor.tt.cs
TrainingHub.BackOffice/Components/CRUD/reg/Forms/CompanyForm.razor
TrainingHub.BackOffice/Components/CRUD/reg/Forms/CompanyForm.razor.tt.cs
File che non devono cambiare:
Company.razor.cs (code-behind custom con servizi inject)
Forms/CompanyForm.razor.cs (SetRiskLevelId, ValidateVatCodeAsync)
5. (Se serve) gestione cross-dominio
Se il nuovo campo deve essere letto da altri domini (es.
noteInterne mostrate nel modulo di fatturazione):
- Rigenera anche il DataLayer se necessario.
- Aggiungi accessor nei code-behind che ne hanno bisogno.
- Attenzione: campi visibili solo ad admin vanno protetti con policy di autorizzazione se esposti in altre sezioni.
6. Test cascade e QueryModifier
Modifiche a companies attivano automaticamente
CompaniesQueryModifier.PostExecutionQuery che ricalcola il rischio
dei workers. Per il nuovo campo noteInterne non è desiderato:
la modifica di note non dovrebbe triggerare cascade rischio (che
però lo fa comunque, perché il modifier non discrimina per campo).
Valutazione: accettabile come side-effect (costo medio-basso) o refactoring per discriminare per campo modificato (costo alto, richiede confronto entity pre/post).
7. Build, test, commit
dotnet build TrainingHub.sln
dotnet test TrainingHub.Tests
git add TrainingHub.Database/reg/Tables/companies.sql
git commit -m "feat(db): add noteInterne to reg.companies"
git add TrainingHub.BackOffice/Components/CRUD/reg/_conf/companies.dxgrid.conf.json
git commit -m "feat(reg): show noteInterne in company form"
git add TrainingHub.BackOffice/Components/CRUD/reg/Company.razor \
TrainingHub.BackOffice/Components/CRUD/reg/Company.razor.tt.cs \
TrainingHub.BackOffice/Components/CRUD/reg/Forms/CompanyForm.razor \
TrainingHub.BackOffice/Components/CRUD/reg/Forms/CompanyForm.razor.tt.cs
git commit -m "regen reg.companies"
⚡ Casi particolari reg
- Campo indirizzo nuovo. Se il campo fa parte dello schema
AddressFormatter(country, province, city, zipCode, address, streetNumber, formattedAddress, latitude, longitude), il componente lo gestisce automaticamente; non serve markup custom. - Campo FK verso altra tabella reg. Il generatore crea
automaticamente un
EditComboBoxcon autorizzazionepage-<scheme>-<table>e popup di edit inline. Se la tabella referenziata è fuori scope (es.companySubcategories), verifica che esista anche il suo CRUD generato. - Campo trigger cascade rischio. Oggi
CompaniesQueryModifierricalcola il rischio a ogniUpdate. Se il tuo campo NON dovrebbe triggerare cascade (es.noteInterne), documenta la scelta ma accetta il costo fino a refactoring del modifier. - Campo con validazione formato. La validazione P.IVA/CF/SDI oggi
non è strutturata; se aggiungi un campo che richiede validazione
(es. un nuovo codice fiscale), implementa la logica in
CompanyForm.razor.cso aspetta un service dedicato futuro.
⚠️ Domande aperte
- Discriminazione cascade rischio per campo. Il
QueryModifierricalcola workers su ogni update company. Per nuovi campi "non rischiosi" (note, logo, ecc.) è overhead. Valutare confronto old vs new entity per triggerare solo su cambi reali adatecoCodeoriskLevelId. - Sensibilità dei nuovi campi. Campi come
noteInternenon devono essere esposti in API o UI cliente. Serve un'annotazione o convention di progetto per marcarli.
🔗 Vedi anche
- Aggiungere un campo
inv— tutorial generale - Panoramica dominio
- Schema DB
- Componenti UI — AddressFormatter, cascade ATECO
- Logica applicativa — QueryModifier