ER-diagram
Ett ER-diagram (Entity-Relationship) är en ritning av databasen. Det visar vilka entiteter som ska lagras, vilka attribut de har, och hur de hänger ihop — och framför allt hur många som hör ihop med hur många. Den vanligaste notationen är kråkfot (crow’s foot), uppkallad efter symbolen för “många” som ser ut som en fågelfot.
När du läst detta ska du kunna
- Känna igen och namnge delarna i ett ER-diagram: entitet, attribut, PK, FK, relation och kardinalitet
- Läsa och rita de fyra kråkfotssymbolerna: exakt ett, noll eller ett, ett eller många, noll eller många
- Avgöra på vilken sida av en relation den främmande nyckeln hamnar
- Översätta ett ER-diagram till entitetsklasser i C# med EF Core
Vad används det till?
- Designa databasen innan du skriver en enda
CREATE TABLEeller entitetsklass - Hitta fel tidigt — ska en order verkligen kunna sakna kund? Det syns direkt i kardinaliteten
- Prata med andra — kunden, läraren eller teamet kan granska datamodellen utan att läsa kod
- Dokumentera en befintlig databas, så att nästa person förstår hur tabellerna hänger ihop
ER-diagrammet beskriver data, inte beteende. Det finns inga metoder här — bara vad som ska sparas och hur det kopplas ihop. Mer om databasen i sig hittar du i SQL-sektionen och på sidan om ER-diagram i SQL.
Delarna och vad de heter
| Del | Hur den ritas | Vad den betyder |
|---|---|---|
| Entitet | Ruta med namnet i en rubrikrad | En sak vi vill spara data om — blir en tabell i databasen och en klass i C# |
| Attribut | En rad i rutan, ofta med datatyp | En egenskap hos entiteten — blir en kolumn och en property |
| Primärnyckel (PK) | Märkt PK, överst och ofta avskild med en linje | Det som gör varje rad unik, t.ex. KundId |
| Främmande nyckel (FK) | Märkt FK | En kolumn som pekar på en annan entitets PK — det är så relationen lagras |
| Relation | Linje mellan två entiteter, gärna med ett verb | Att entiteterna hör ihop: “en kund lägger ordrar” |
| Kardinalitet | Symboler i linjens ändar (se nedan) | Hur många på den ena sidan som hör ihop med en på den andra |
Läs relationen åt båda håll, och läs alltid symbolen vid den bortre entiteten: “En kund lägger noll eller många ordrar” (symbolen vid Order). “En order läggs av exakt en kund” (symbolen vid Kund).
De fyra kråkfotssymbolerna
Varje ände består av två tecken. Det inre tecknet (närmast entiteten) är max, det yttre är min. En ring betyder noll, ett streck betyder ett och kråkfoten betyder många.
| Symbol | Utläses | Min | Max | Typiskt i C# |
|---|---|---|---|---|
| Två streck | Exakt ett | 1 | 1 | Kund Kund (krävs) |
| Ring + streck | Noll eller ett | 0 | 1 | Kundkort? Kundkort (nullable) |
| Streck + kråkfot | Ett eller många | 1 | många | List<OrderRad> — “minst en” kontrolleras i koden |
| Ring + kråkfot | Noll eller många | 0 | många | List<Order> (får vara tom) |
Var hamnar FK? Alltid på många-sidan. En kund har många ordrar, så det är Order som får kolumnen KundId — inte tvärtom. En kund kan ju inte ha en kolumn per order.
Exempel — webbshop: Kund, Order, OrderRad och Produkt
En kund lägger ordrar. En order består av en eller flera orderrader, och varje orderrad gäller en produkt. OrderRad är kopplingsentiteten som löser många-till-många mellan Order och Produkt — och den bär egen data: antal och styckpris vid köptillfället.
Läs det högt, så märker du om något är fel:
- En kund lägger noll eller många ordrar. En order läggs av exakt en kund.
- En order innehåller en eller många orderrader. En orderrad hör till exakt en order.
- En produkt finns på noll eller många orderrader. En orderrad gäller exakt en produkt.
Styckpris ligger på OrderRad och inte bara på Produkt — annars skulle gamla ordrar plötsligt ändra pris när du höjer priset på produkten.
Samma modell som EF Core-entiteter
Varje entitet blir en klass, varje attribut en property, och varje relation blir en FK-property plus en navigation property. Många-sidan får en lista. (Läs mer i Entity Framework, särskilt Entiteter och Relationer.)
public class Kund{ public int KundId { get; set; } // PK — EF hittar "<Klass>Id" själv public string Namn { get; set; } = ""; public string Epost { get; set; } = ""; public string? Telefon { get; set; } // nullable = får saknas
public List<Order> Ordrar { get; set; } = new(); // noll eller många}
public class Order{ public int OrderId { get; set; } // PK public DateTime Datum { get; set; } public string Status { get; set; } = "Ny";
public int KundId { get; set; } // FK → Kund public Kund Kund { get; set; } = null!; // exakt en
public List<OrderRad> Rader { get; set; } = new(); // en eller många (kontrolleras i koden)}
public class OrderRad{ public int OrderRadId { get; set; } // PK public int Antal { get; set; } [Precision(10, 2)] public decimal Styckpris { get; set; }
public int OrderId { get; set; } // FK → Order public Order Order { get; set; } = null!;
public int ProduktId { get; set; } // FK → Produkt public Produkt Produkt { get; set; } = null!;}
public class Produkt{ public int ProduktId { get; set; } // PK public string Namn { get; set; } = ""; [Precision(10, 2)] public decimal Pris { get; set; } public int Lagersaldo { get; set; }
public List<OrderRad> OrderRader { get; set; } = new(); // noll eller många}
public class ShopContext : DbContext{ public DbSet<Kund> Kunder => Set<Kund>(); public DbSet<Order> Ordrar => Set<Order>(); public DbSet<OrderRad> OrderRader => Set<OrderRad>(); public DbSet<Produkt> Produkter => Set<Produkt>();}Lägg märke till skillnaden mellan “noll” och “ett” som minimum:
- Exakt ett (
int KundId, inteint?) → kolumnen blirNOT NULLi databasen. En order kan inte sparas utan kund. - Noll eller ett skulle bli
int? KundId→ kolumnen tillåterNULL. - Ett eller många kan databasen inte tvinga fram — det finns ingen constraint för “minst en rad i en annan tabell”. Det kontrollerar du i koden innan du sparar, t.ex.
if (order.Rader.Count == 0) throw ....
ER-diagram eller UML-klassdiagram?
De ser lika ut — rutor med namn och fält, linjer emellan — men de svarar på olika frågor.
| ER-diagram | UML-klassdiagram | |
|---|---|---|
| Beskriver | Hur data lagras | Hur koden är uppbyggd |
| Innehåll | Attribut, PK, FK | Fält, properties och metoder, synlighet (+/-) |
| Relationer | Bara kopplingar och kardinalitet | Association, arv, komposition, implementation av interface |
| Kardinalitet | Kråkfot i linjens ände | Siffror: 1, 0..1, 1..*, * |
| Främmande nycklar | Ritas ut (FK KundId) | Syns inte — objekt pekar direkt på varandra |
| Arv | Finns inte (tabeller ärver inte) | Central del |
Tumregel: rita ER-diagram när du designar databasen, och klassdiagram när du designar koden. Med EF Core ligger de nära varandra, men klassdiagrammet har metoder och arv som databasen aldrig ser, och ER-diagrammet har FK-kolumner som du i koden mest använder via navigation properties.
När ska du välja ett ER-diagram?
| Välj ER-diagram när… | Välj något annat när… |
|---|---|
| Du ska skapa eller ändra tabeller | Du vill visa klasser med metoder och arv → klassdiagram |
| Du vill diskutera kardinalitet: “kan en order sakna kund?” | Du vill visa hur data rör sig mellan processer → dataflödesdiagram |
| Du ska skriva EF Core-entiteter eller migrationer | Du vill visa i vilken ordning saker anropas → sekvensdiagram |
| Du dokumenterar en befintlig databas | Du vill visa hela systemets delar (API, databas, klient) → arkitekturdiagram |
Vanliga misstag
- FK på fel sida. Den främmande nyckeln ligger på många-sidan.
Kundska inte haOrderId. - Många-till-många utan kopplingsentitet. En relationsdatabas kan inte lagra N:M direkt. Rita ut
OrderRad(eller motsvarande) — det är ändå där intressant data som antal och pris ofta bor. - Symbolen läses vid fel entitet. “En kund lägger många ordrar” läses vid
Order-änden. Säg meningen högt åt båda håll. - Glömt minimum. Att bara rita kråkfot (“många”) säger inget om noll är tillåtet. Bestäm om det ska vara ring eller streck — det avgör
NOT NULL. - Metoder i ER-diagrammet.
BeräknaTotal()hör hemma i klassdiagrammet, inte här.
Övning
Rita ett ER-diagram för ett bibliotek med entiteterna Låntagare, Lån, Exemplar och Bok:
- En låntagare kan ha noll eller många lån. Ett lån tillhör exakt en låntagare.
- Ett lån gäller exakt ett exemplar. Ett exemplar kan ha lånats noll eller många gånger.
- En bok har ett eller många exemplar. Ett exemplar är av exakt en bok.
Markera PK och FK i varje entitet. Skriv sedan entitetsklasserna i C# och fundera: vilken av relationerna kan databasen inte tvinga fram, och var i koden skulle du kontrollera den?
TL;DR
| Begrepp | Vad det är |
|---|---|
| Entitet | Ruta = tabell = klass |
| Attribut | Rad i rutan = kolumn = property |
| PK / FK | Unik nyckel / pekare till en annan entitets PK (ligger på många-sidan) |
| Kråkfot | “Många” — inre symbolen är max, yttre är min |
| Ring / streck | Noll / ett |
| Skillnad mot klassdiagram | ER = hur data lagras; klassdiagram = hur koden är byggd |