Prototypowanie bazy danych z Entity Framework

Duże jest na początku małe. Potem rośnie. Dotyczy to także oprogramowania. Zanim zrobię „dużą” bazę, to czasem mam potrzebę wykonania prototypu. Nie musi on odzwierciedlać wszystkich encji, ale te których powiązania chcę sprawdzić. Po co tak? W przypadku Entity Framework, warto popatrzeć, co wyprodukuje framework czy to z modeli i 'annotations’, czy z kodu fluent api. To nie jest to T-SQL, gdzie widzę, co piszę 😉 Dlatego szybki prototyp się przydaje. W tym celu robię sobie migrację i aplikuję ją do bazy. Wtedy widać jaka będzie finalna postać moich zamierzeń. Mogę ją też przetestować.

Nie przedłużając, bo to ma być szybki prototyp a pizza już jest w piekarniku, zabieramy się do pracy 😉

Robimy sobie folder na naszą aplikację, w której utworzymy modele encji. Zakładam, że .NET SDK i MSSQL Server mamy zainstalowane. Potrzebne też będzie narzędzie dotnet-ef. Kto ma, to pomija pierwsze polecenie.

dotnet tool install --global dotnet-ef
md Alamakota
cd Alamakota
donet new console
dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Design

Środowisko testowe mamy gotowe. Teraz przyszedł czas na obiekt, który będzie testowany. Otwieramy projekt w ulubionym IDE i dodajemy DbContext.

using Alamakota.Entities;
using Microsoft.EntityFrameworkCore;

namespace Alamakota;

public class ApplicationContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(@"Data Source=.\SQLEXPRESS;Initial Catalog=ala-test;Integrated Security=True;Trust Server Certificate=Yes");
    }
}

To sprawdźmy, czy wszystko jest w porządku? Poniższa komenda powinna zbudować aplikację i zwrócić wynik:
C:\Users\marek\Alamakota> dotnet ef migrations list
Build started…
Build succeeded.
No migrations were found.

Fakt, nie mamy jeszcze migracji, ani bazy, ale wiemy, że aplikacja się buduje i mamy połączenie z serwerem. To czas na jakieś modele, np.

namespace Alamakota.Entities;

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; } = null!;

    public virtual ICollection<Friendship>? Friendships { get; set; }
}

public class Friendship
{
    public int Id { get; set; }
    public virtual ICollection<Person>? Persons { get; set; }
}

Uzupełniamy ApplicationContext dodając poniżej metody OnConfiguring obiekty DbSet<> i inicjalizujemy bazę danymi.

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Person>().HasData(new Person { Id = 1, Name = "Ala" });
        modelBuilder.Entity<Person>().HasData(new Person { Id = 2, Name = "Bolek" });
        modelBuilder.Entity<Person>().HasData(new Person { Id = 3, Name = "Lolek" });
    }

    public DbSet<Person> Persons { get; set; } = null!;
    public DbSet<Friendship> Friendships { get; set; } = null!;

Następnie tworzymy pierwszą migrację oraz aplikujemy ją do bazy.
C:\Users\marek\Alamakota> dotnet ef migrations add initial
C:\Users\marek\Alamakota> dotnet ef database update

Serwer powinien pokazać nową bazę i tabele.

I to by było w zasadzie wszystko, co istotne. Mamy bazę, której strukturę chcieliśmy sprawdzić. Dla mnie najważniejszy jest plik ApplicationContextModelSnapshot.cs który Entity Framework utworzył w folderze Migrations. W nim widzę, jak framework przełożył mój kod na polecenia fluent api, które są odzwierciedlane w bazie danych. Trzeba jednak pamiętać, że ten kod, nie pokazuje w 100% tego co się wydarzy w bazie. Framework posługuje się pewnymi ustawieniami domyślnymi. W kodzie fluent api nie wszystko jest uwidocznione. Np. domyślnie na kluczu głównym zakładany jest indeks klastrowy, a w kodzie tego nie widać. Zawsze jednak można sobie z poziomu MSSMS wygenerować skrypt odtwarzający interesujący element, np. tabelę. Tam już nic nam nie umknie 🙂

Na zakończenie wisienka na torcie. Sprawdźmy, że nasz DbContext sięgnie dane z bazy. Zamieniamy zawartość Program.cs na następującą:

using Alamakota;

using var dbContext = new ApplicationContext();
var persons = dbContext.Persons;

foreach (var person in persons)
{
    Console.WriteLine(person.Name);
}

I po wydaniu komendy dotnet run powinniśmy zobaczyć:
Ala
Bolek
Lolek

Pizza gotowa. To już wszystko na dziś 🙂

Dodaj komentarz