En solid datamodel er fundamentet for enhver succesfuld Power Platform-løsning. Men hvor starter man? Og hvordan undgår man de klassiske faldgruber? I denne artikel deler vi vores tilgang til datamodellering i Dataverse.
Hvorfor er datamodellering vigtigt?
En dårlig datamodel kan sabotere selv den bedste app. Problemerne viser sig typisk ikke med det samme, men når løsningen skal skalere eller udvides:
- Performance-problemer: Langsomme queries når data vokser
- Kompleksitet: Svært at vedligeholde og udvide
- Data-kvalitet: Inkonsistente data og dupliketter
- Begrænset fleksibilitet: Svært at tilføje nye krav
Vi har set organisationer bruge 100+ timer på at redesigne datamodeller fordi de ikke fik det rigtigt fra start. Det er dyrt og smertefuldt.
De grundlæggende byggeklodser
Tables (Tabeller)
Dataverse bruger tables (tidligere kaldet entities) til at gemme data. Tænk på dem som tabeller i en database, men med mere intelligens:
Account (Kunde)
├── Felter: Name, Email, Phone, Industry
├── Relationer: One-to-Many med Opportunities
├── Business rules
└── Workflows
Standard vs. Custom Tables:
- Standard tables: Account, Contact, Opportunity osv. - brug dem hvor det giver mening
- Custom tables: Opret når standard-tables ikke dækker dit behov
Naming convention: Brug beskrivende navne (ikke "Data1" eller "TempTable"). Vi anbefaler præfix for custom tables, f.eks. iseni_Project.
Columns (Felter)
Vælg den rigtige datatype fra start:
| Datatype | Hvornår du bruger den | Eksempel | |----------|----------------------|----------| | Text | Generisk tekst | Navn, beskrivelse | | Choice | Foruddefinerede værdier | Status, Type, Prioritet | | Lookup | Reference til anden tabel | Customer → Account | | Date | Datoer | CreatedOn, Deadline | | Number | Numerisk data | Pris, Mængde | | Currency | Pengebeløb | Revenue, Cost |
Brug Choice columns (OptionSets) frem for text når du har foruddefinerede værdier. Det giver bedre data-kvalitet og lettere filtrering.
Relationships (Relationer)
Dataverse understøtter tre typer relationer:
1. One-to-Many (1:N) En Account har mange Contacts.
Account (1) ──→ (N) Contact
2. Many-to-One (N:1) Mange Contacts tilhører én Account (samme som ovenstående, set fra Contact's perspektiv).
3. Many-to-Many (N:N) Mange Projects har mange Employees, og omvendt.
Project (N) ←─→ (N) Employee
Best practice: Start med 1:N og N:1. Brug kun N:N når det er absolut nødvendigt (de er mere komplekse at arbejde med).
Vores 7-trins design-proces
1. Start med forretningsobjekter
Identificér de centrale forretningsobjekter (ikke tekniske tabeller):
Eksempel: Projektledelsessystem
- Projekt
- Kunde
- Opgave
- Medarbejder
- Timeregistrering
Ikke: User, Log, Setting (det er tekniske objekter)
2. Definér attributter for hvert objekt
For hver entitet: Hvad skal vi vide?
Projekt
├── Navn (text)
├── Beskrivelse (multiline text)
├── Start dato (date)
├── Slut dato (date)
├── Status (choice: Planlagt, I gang, Afsluttet)
├── Budget (currency)
└── Projektleder (lookup til Medarbejder)
Tip: Hold det simpelt. Start med minimum, udvid senere.
3. Identificér relationer
Hvordan hænger objekterne sammen?
Kunde (1) ──→ (N) Projekt
Projekt (1) ──→ (N) Opgave
Medarbejder (N) ←─→ (N) Projekt (via Timeregistrering)
Rød flag: Hvis alt hænger sammen med alt, er din model sandsynligvis for kompleks. Overvej at splitte den op.
4. Normalisering (men ikke for meget)
Normaliser for at undgå redundans: ❌ Gem ikke kunde-navn både på Project og Task ✅ Brug lookup til Customer
Men overnormalisér ikke: ❌ Opret ikke en tabel for hvert lille felt ✅ Det er OK at denormalisere lidt for performance
5. Overve udvidelsesmuligheder
Tænk 6-12 måneder frem:
- Skal vi støtte flere valutaer senere?
- Kan vi få brug for at versione data?
- Skal vi håndtere kompleks godkendelse?
Men gæt ikke for vidt. Design for kendte krav + lidt flexibilitet.
6. Valider med stakeholders
Gennemgå modellen med:
- Forretningsbrugere: "Giver det mening?"
- Udviklere: "Kan vi bygge det?"
- Arkitekter: "Skalerer det?"
7. Prototype og iterate
Byg en lille prototype:
- Opret tabeller og felter
- Lav test-data
- Byg en simpel app ovenpå
Hvis noget føles forkert, er det nok fordi det er forkert. Juster modellen nu, ikke efter go-live.
Avancerede mønstre
Polymorphic Lookups
Har du brug for at en opgave kan referere til enten en Account ELLER en Contact?
Brug polymorphic lookups (Customer-feltet kan pege på både Account og Contact).
Parent-Child Hierarchies
Har du hierarkiske data (f.eks. organisation, kategorier)?
Brug self-referencing relationships:
Account (Parent Account) ──→ Account (Child Account)
Dataverse understøtter rollup-queries op gennem hierarkiet.
Managed vs. Unmanaged Solutions
Unmanaged: Til development Managed: Til deployment til test/prod
Designmæssigt betyder det:
- Prefix alle custom tables/fields (f.eks.
iseni_) - Gør det muligt at pakke som managed solution senere
Performance-overvejelser
Indexering
Dataverse indexerer automatisk:
- Primary key
- Lookup fields
- Nogle standard fields
Men du kan tilføje custom indexes på felter du ofte filtrerer/sorterer på.
Eksempel: Hvis du ofte søger projekter efter startdato, tilføj index på iseni_startdate.
Rollup vs. Calculated Fields
Calculated fields: Beregnes on-the-fly (ingen database-belastning)
FullName = FirstName + " " + LastName
Rollup fields: Aggregerer data fra relaterede records
TotalRevenue = SUM af alle Opportunities.Revenue
⚠️ Rollups kan være dyre performance-mæssigt. Overvej at beregne dem async og cache resultatet.
Sikkerhed og adgangsstyring
Din datamodel skal understøtte sikkerhed:
Business Units
Hvis du har flere afdelinger/teams der skal have separate data:
Organization
├── BU: Sales (adgang til Sales-projekter)
├── BU: Marketing (adgang til Marketing-projekter)
└── BU: IT (adgang til alle projekter)
Field-Level Security
Følsomme felter (f.eks. løn, CPR) kan beskyttes på feltniveau.
Eksempel: Kun HR-teamet kan se Salary-feltet.
Custom Security Roles
Definer roller baseret på jobfunktion:
- Project Manager: Full access til Projects
- Team Member: Read-only på Projects, write på own Tasks
- Executive: Read-only på alt + dashboards
Common Mistakes (og hvordan du undgår dem)
❌ Mistake 1: At bruge text hvor du skulle bruge choice
Problem: "Status" som fritekst → inkonsistente værdier ("I gang", "Igang", "In progress")
Løsning: Brug Choice column med foruddefinerede værdier.
❌ Mistake 2: At gemme lister i et enkelt felt
Problem: "Tags" som comma-separated text → svært at søge, filtrere
Løsning: Opret en N:N relation til en Tag-tabel.
❌ Mistake 3: At overnormalisere
Problem: 15 tabeller for en simpel løsning → complexity-overload
Løsning: Start enkelt. Refaktorer senere hvis nødvendigt.
❌ Mistake 4: Ingen naming convention
Problem: Tabeller hedder "Data1", "CustomerInfo", "CustList" → forvirring
Løsning: Definer og følg en naming convention.
Værktøjer vi bruger
1. XrmToolBox
Fantastisk community-tool til Dataverse. Vi bruger især:
- Schema Browser: Visualiser relationer
- FetchXML Builder: Test queries
- Metadata Document Generator: Generér dokumentation
2. ER/Studio eller Draw.io
Til at tegne ER-diagrammer før vi bygger i Dataverse.
3. PowerShell / CLI
Til at automatisere oprettelse af tabeller (især nyttigt hvis du har mange).
Konklusion
En god datamodel tager tid at designe, men betaler sig mange gange igen:
Fordele
- ✓Start simpelt, udvid gradvist
- ✓Involvér stakeholders tidligt
- ✓Dokumentér dine design-beslutninger
- ✓Brug standard tables hvor det giver mening
- ✓Tænk på performance fra start
Ulemper
- ✗Overnormalisér ikke
- ✗Gæt ikke på fremtidige krav
- ✗Ignorer ikke sikkerhed
- ✗Glem ikke naming conventions
En veldesignet datamodel er forskellen mellem en løsning der bare fungerer, og en løsning der fungerer godt i årevis.
Har du brug for hjælp til at designe din datamodel?
Vi tilbyder datamodellerings-workshops og arkitektur-reviews.