Kapitel 6 – Reflektion och jämförelse

1. När använder man vilken databas?

SQLite

Använd när:

  • ✅ Du bygger en desktop- eller mobilapp
  • ✅ Projektet är litet/prototyp
  • ✅ Endast en användare åt gången
  • ✅ Du vill ha enkel deployment (en fil)
  • ✅ Ingen nätverksåtkomst behövs

Exempel:

  • Anteckningsappar
  • Lokala inställningar
  • Utvecklings-/testdatabaser
  • Embedded systems

MySQL

Använd när:

  • ✅ Du bygger en webbapplikation
  • ✅ Många samtidiga användare
  • ✅ Open source är viktigt
  • ✅ LAMP-stack (Linux, Apache, MySQL, PHP)
  • ✅ Community och plugins är viktigt

Exempel:

  • WordPress-sajter
  • E-handel
  • CMS-system
  • Webbforum

SQL Server / LocalDB

Använd när:

  • ✅ Du arbetar i Microsoft-ekosystemet
  • ✅ Windows-baserade företagssystem
  • ✅ Integration med Azure
  • ✅ Avancerade features (BI, reporting)
  • ✅ Enterprise-support behövs

Exempel:

  • Företagsapplikationer
  • .NET-baserade system
  • Azure-integrationer
  • Data warehouse

MongoDB

Använd när:

  • ✅ Flexibelt schema behövs
  • ✅ JSON/API-baserad data
  • ✅ Horisontell skalning är viktigt
  • ✅ Hierarkisk data (dokument med subdokument)
  • ✅ Snabb iterativ utveckling

Exempel:

  • Content management
  • Real-time analytics
  • IoT-data
  • Katalogsystem med varierande produktegenskaper

2. Skillnader mellan SQL och NoSQL

Datamodell

AspektSQLNoSQL (MongoDB)
StrukturTabeller, rader, kolumnerCollections, dokument
SchemaFast, definierat i förvägFlexibelt, kan ändras
RelationerForeign keys + JOINsEmbedded documents eller referenser
DatatyperStrikta (INT, VARCHAR)JSON-liknande (String, Number, Array, Object)

Query-språk

SQL:

SELECT c.Name, o.OrderDate, o.TotalAmount
FROM Customers c
INNER JOIN Orders o ON c.CustomerId = o.CustomerId
WHERE c.City = 'Stockholm'
ORDER BY o.OrderDate DESC;

MongoDB:

db.customers.aggregate([
  {
    $match: { "address.city": "Stockholm" }
  },
  {
    $lookup: {
      from: "orders",
      localField: "_id",
      foreignField: "customerId",
      as: "orders"
    }
  },
  {
    $unwind: "$orders"
  },
  {
    $sort: { "orders.orderDate": -1 }
  }
])

Men oftast i MongoDB:

// Embedded approach - inga JOINs!
db.customers.find({
  "address.city": "Stockholm"
})

Transaktioner

SQL:

  • ✅ ACID-garantier (Atomicity, Consistency, Isolation, Durability)
  • ✅ Transaktioner över flera tabeller
  • ✅ Rollback vid fel

MongoDB:

  • ⚠️ ACID på dokumentnivå (MongoDB 4.0+)
  • ⚠️ Multi-document transactions finns men används sällan
  • ✅ Atomic operations på ett dokument

Skalning

SQL (Vertikal skalning):

Liten server → Större server → Ännu större server
  • Begränsad av hårdvara
  • Dyrt att skala

NoSQL (Horisontell skalning):

1 server → 3 servrar → 10 servrar → 100 servrar
  • Obegränsad skalning (teoretiskt)
  • Billigare att lägga till fler “små” servrar

3. Samma app i olika databaser

Låt oss bygga en enkel kundapp i alla fyra databaser!

Exempel: Kundregister med adresser

SQLite / MySQL / SQL Server (identisk kod med EF Core)

Modeller:

public class Customer
{
    public int CustomerId { get; set; }
    public string Name { get; set; } = string.Empty;
    public string Email { get; set; } = string.Empty;
    public Address Address { get; set; } = null!;
}

public class Address
{
    public int AddressId { get; set; }
    public int CustomerId { get; set; }
    public string Street { get; set; } = string.Empty;
    public string City { get; set; } = string.Empty;
    public string Zip { get; set; } = string.Empty;
}

DbContext:

public class AppDbContext : DbContext
{
    public DbSet<Customer> Customers { get; set; }
    public DbSet<Address> Addresses { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        // SQLite
        optionsBuilder.UseSqlite("Data Source=app.db");

        // MySQL
        // optionsBuilder.UseMySql("Server=localhost;Database=myapp;...", ServerVersion.AutoDetect(...));

        // SQL Server
        // optionsBuilder.UseSqlServer("Server=(localdb)\\MSSQLLocalDB;Database=MyApp;...");
    }
}

CRUD:

// CREATE
using (var context = new AppDbContext())
{
    var customer = new Customer
    {
        Name = "Anna",
        Email = "anna@example.com",
        Address = new Address
        {
            Street = "Storgatan 1",
            City = "Stockholm",
            Zip = "11122"
        }
    };
    context.Customers.Add(customer);
    context.SaveChanges();
}

// READ
using (var context = new AppDbContext())
{
    var customers = context.Customers
        .Include(c => c.Address)
        .Where(c => c.Address.City == "Stockholm")
        .ToList();
}

// UPDATE
using (var context = new AppDbContext())
{
    var customer = context.Customers.Find(1);
    customer.Email = "newemail@example.com";
    context.SaveChanges();
}

// DELETE
using (var context = new AppDbContext())
{
    var customer = context.Customers.Find(1);
    context.Customers.Remove(customer);
    context.SaveChanges();
}

MongoDB (embedded document approach)

Modeller:

public class Customer
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string? Id { get; set; }

    [BsonElement("name")]
    public string Name { get; set; } = string.Empty;

    [BsonElement("email")]
    public string Email { get; set; } = string.Empty;

    [BsonElement("address")]
    public Address Address { get; set; } = null!;
}

public class Address
{
    [BsonElement("street")]
    public string Street { get; set; } = string.Empty;

    [BsonElement("city")]
    public string City { get; set; } = string.Empty;

    [BsonElement("zip")]
    public string Zip { get; set; } = string.Empty;
}

Anslutning:

var client = new MongoClient("mongodb://localhost:27017");
var database = client.GetDatabase("myapp");
var collection = database.GetCollection<Customer>("customers");

CRUD:

// CREATE
var customer = new Customer
{
    Name = "Anna",
    Email = "anna@example.com",
    Address = new Address
    {
        Street = "Storgatan 1",
        City = "Stockholm",
        Zip = "11122"
    }
};
await collection.InsertOneAsync(customer);

// READ
var customers = await collection
    .Find(c => c.Address.City == "Stockholm")
    .ToListAsync();

// UPDATE
var filter = Builders<Customer>.Filter.Eq(c => c.Id, customerId);
var update = Builders<Customer>.Update.Set(c => c.Email, "newemail@example.com");
await collection.UpdateOneAsync(filter, update);

// DELETE
var filter = Builders<Customer>.Filter.Eq(c => c.Id, customerId);
await collection.DeleteOneAsync(filter);

4. Vanliga misstag och lösningar

SQL-databaser

Misstag: Glömma SaveChanges() i EF Core

context.Customers.Add(customer); // Sparas inte!
// context.SaveChanges(); // Behövs!

Misstag: N+1 query problem

foreach (var customer in context.Customers.ToList())
{
    Console.WriteLine(customer.Address.City); // En query per kund!
}

Lösning: Använd Include()

var customers = context.Customers.Include(c => c.Address).ToList();

Misstag: SQL injection

string sql = $"SELECT * FROM Users WHERE Username = '{username}'"; // FARLIGT!

Lösning: Parametriserade queries

command.CommandText = "SELECT * FROM Users WHERE Username = @username";
command.Parameters.AddWithValue("@username", username);

MongoDB

Misstag: Försöka använda JOINs

// MongoDB har inte JOINs som SQL!

Lösning: Embedded documents eller $lookup (aggregation)

Misstag: Glömma async/await

var customers = collection.Find(_ => true).ToListAsync(); // Returnerar Task!

Lösning:

var customers = await collection.Find(_ => true).ToListAsync();

Misstag: Fel datatyp för _id

public int Id { get; set; } // MongoDB använder ObjectId!

Lösning:

[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string? Id { get; set; }

5. Sammanfattande kommando- och verktygstabell

DatabasVerktygConnection String ExempelNuGet-paket
SQLiteDB Browser for SQLiteData Source=app.dbMicrosoft.Data.Sqlite
Microsoft.EntityFrameworkCore.Sqlite
MySQLphpMyAdmin, MySQL WorkbenchServer=localhost;Port=3306;Database=myapp;User=root;Password=pass;MySql.Data
Pomelo.EntityFrameworkCore.MySql
LocalDBSSMSServer=(localdb)\MSSQLLocalDB;Database=MyApp;Integrated Security=true;Microsoft.Data.SqlClient
Microsoft.EntityFrameworkCore.SqlServer
SQL ServerSSMSServer=localhost,1433;Database=MyApp;User Id=sa;Password=pass;Microsoft.Data.SqlClient
Microsoft.EntityFrameworkCore.SqlServer
MongoDBMongoDB Compassmongodb://localhost:27017MongoDB.Driver

Slutsats

Du har nu en komplett överblick över:

Filbaserad databas (SQLite) – enkel, lokal ✅ Klassisk serverdatabas (MySQL) – open source, webben ✅ Microsoft-stacken (LocalDB/SQL Server) – enterprise, .NET ✅ Containeriserad databas (Docker) – modern deployment ✅ Dokumentdatabas (MongoDB) – flexibel, NoSQL

Nästa steg i din databasresa

  1. Bygg projekt: Skapa samma app i alla databaser för att förstå skillnaderna
  2. Lär dig optimering: Indexering, query optimization
  3. Utforska avancerade features:
    • Stored procedures (SQL)
    • Triggers och views
    • Aggregation pipelines (MongoDB)
  4. Säkerhet: Lär dig om SQL injection, autentisering, kryptering
  5. Cloud: Utforska Azure SQL, MongoDB Atlas, AWS RDS

Grattis – du har nu kunskapen att välja och använda rätt databas för varje projekt! 🎉


Upp

Upp


Licens: Apache 2.0 | © 2023 Marcus Medina, Campus Mölndal. Alla rättigheter förbehållna.
Du får använda och modifiera detta verk enligt villkoren i Apache License, Version 2.0. Du får inte använda detta verk för kommersiella ändamål utan tillstånd från upphovsmannen.