Przejdź do treści

MongoDB i Entity Framework Core – praktyczny przewodnik

  • przez

Entity Framework Core (EF Core) to popularny ORM dla platformy .NET, który pozwala programistom pracować z bazami danych za pomocą obiektów C# zamiast pisania surowych zapytań. Dzięki MongoDB EF Core Provider te same znane wzorce można teraz stosować z bazą NoSQL, jaką jest MongoDB.

W tym artykule dowiesz się, jak połączyć MongoDB z EF Core, poznasz kluczowe koncepcje i zobaczysz praktyczny przykład, który możesz zaadaptować do własnych projektów.

Dlaczego MongoDB + EF Core?

MongoDB przechowuje dane jako elastyczne dokumenty w formacie JSON (BSON) w kolekcjach – bez sztywnych schematów tabel. EF Core z kolei daje programistom .NET spójne API do dostępu do danych z zapytaniami LINQ, śledzeniem zmian i podejściem code-first. Połączenie obu technologii oznacza elastyczność MongoDB z wygodnymi wzorcami EF Core.

Główne zalety MongoDB EF Core Provider:

  • Podejście code-first – definiujesz modele w C#, a EF Core zajmuje się resztą
  • Wsparcie LINQ – zapytania do MongoDB przy użyciu standardowej składni LINQ
  • Śledzenie zmian (change tracking) – automatyczne wykrywanie modyfikacji encji
  • Dokumenty zagnieżdżone – natywne wsparcie dla obiektów osadzonych
  • Znajome API – jeśli znasz EF Core z SQL Server, przejście jest płynne

Rozpoczęcie pracy

Wymagania

  • .NET 7.0+ SDK
  • Konto MongoDB Atlas (dostępny darmowy plan) lub lokalna instancja MongoDB
  • Ulubione IDE (Visual Studio, VS Code, Rider)

Instalacja pakietu NuGet

dotnet add package MongoDB.EntityFrameworkCore

Pakiet automatycznie instaluje MongoDB C# Driver i EF Core jako zależności.

Praktyczny przykład: Katalog produktów

Zbudujemy prosty katalog produktów, aby zademonstrować wszystkie operacje CRUD.

1. Definicja modelu

using MongoDB.Bson;
using MongoDB.EntityFrameworkCore;

namespace MyApp.Models
{
    [Collection("products")]
    public class Product
    {
        public ObjectId Id { get; set; }
        public string Name { get; set; } = string.Empty;
        public decimal Price { get; set; }
        public string Category { get; set; } = string.Empty;
        public List<string> Tags { get; set; } = new();
    }
}

Atrybut [Collection("products")] mapuje tę klasę na kolekcję products w MongoDB. Zwróć uwagę na właściwość Tags – MongoDB obsługuje tablice natywnie, co w relacyjnej bazie wymagałoby osobnej tabeli.

2. Tworzenie DbContext

using Microsoft.EntityFrameworkCore;
using MyApp.Models;

namespace MyApp.Data
{
    public class ProductDbContext : DbContext
    {
        public DbSet<Product> Products { get; init; }

        public ProductDbContext(DbContextOptions options) : base(options) { }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Entity<Product>();
        }
    }
}

3. Konfiguracja połączenia

using MongoDB.Driver;
using Microsoft.EntityFrameworkCore;
using MyApp.Data;

// Tworzenie klienta MongoDB
var mongoClient = new MongoClient("mongodb+srv://<user>:<password>@cluster0.xxxxx.mongodb.net");

// Konfiguracja DbContext z MongoDB
var dbContextOptions = new DbContextOptionsBuilder<ProductDbContext>()
    .UseMongoDB(mongoClient, "my_store")
    .Options;

var db = new ProductDbContext(dbContextOptions);

4. Operacje CRUD

Tworzenie (Create)

var newProduct = new Product
{
    Name = "Klawiatura mechaniczna",
    Price = 149.99m,
    Category = "Elektronika",
    Tags = new List<string> { "peryferia", "gaming", "biuro" }
};

db.Products.Add(newProduct);
db.SaveChanges();

Console.WriteLine($"Dodano produkt z ID: {newProduct.Id}");

Odczyt (Read)

// Wszystkie produkty z danej kategorii
var elektronika = db.Products
    .Where(p => p.Category == "Elektronika")
    .OrderBy(p => p.Price)
    .ToList();

foreach (var product in elektronika)
{
    Console.WriteLine($"{product.Name} – {product.Price:C}");
}

// Pojedynczy produkt po warunku
var klawiatura = db.Products
    .FirstOrDefault(p => p.Name == "Klawiatura mechaniczna");

Aktualizacja (Update)

var productToUpdate = db.Products
    .FirstOrDefault(p => p.Name == "Klawiatura mechaniczna");

if (productToUpdate != null)
{
    productToUpdate.Price = 129.99m;
    productToUpdate.Tags.Add("wyprzedaz");
    db.SaveChanges();
}

Usuwanie (Delete)

var productToDelete = db.Products
    .FirstOrDefault(p => p.Name == "Klawiatura mechaniczna");

if (productToDelete != null)
{
    db.Products.Remove(productToDelete);
    db.SaveChanges();
}

Użycie w ASP.NET Core

W prawdziwej aplikacji webowej rejestrujesz DbContext w Program.cs:

// Program.cs
var connectionString = builder.Configuration.GetConnectionString("MongoDB");
var databaseName = builder.Configuration["MongoDBSettings:DatabaseName"];

builder.Services.AddDbContext<ProductDbContext>(options =>
    options.UseMongoDB(connectionString ?? "", databaseName ?? ""));

A w appsettings.json:

{
  "ConnectionStrings": {
    "MongoDB": "mongodb+srv://<user>:<password>@cluster0.xxxxx.mongodb.net"
  },
  "MongoDBSettings": {
    "DatabaseName": "my_store"
  }
}

Następnie wstrzykujesz kontekst do kontrolerów lub serwisów:

public class ProductsController : Controller
{
    private readonly ProductDbContext _db;

    public ProductsController(ProductDbContext db)
    {
        _db = db;
    }

    public IActionResult Index()
    {
        var products = _db.Products.OrderBy(p => p.Name).Take(50).ToList();
        return View(products);
    }
}

Warto wiedzieć

  • Brak wsparcia dla relacji – MongoDB EF Core Provider nie obsługuje jeszcze właściwości nawigacyjnych ani relacji między encjami. Można to obejść, przechowując powiązane ID i odpytując ręcznie.
  • Dokumenty zagnieżdżone działają świetnie – zamiast joinów modeluj dane zagnieżdżone jako właściwości encji.
  • Zaawansowane funkcje – do Atlas Search lub Vector Search używaj MongoDB C# Driver bezpośrednio obok EF Core.
  • Śledzenie zmian – działa tak samo jak z bazami relacyjnymi; do MongoDB wysyłane są tylko zmodyfikowane pola.

Podsumowanie

MongoDB EF Core Provider pozwala programistom .NET korzystać ze znanego API EF Core z bazą MongoDB, łącząc najlepsze cechy obu światów. Definiujesz modele w C#, używasz LINQ do zapytań, a EF Core zajmuje się resztą. W przypadku większości operacji CRUD doświadczenie jest niemal identyczne jak przy użyciu EF Core z SQL Server – z dodatkową elastycznością bazy dokumentowej.