Back to "Hinzufügen des Entity Framework für Blog-Posts (Teil 2)"

This is a viewer only at the moment see the article on how this works.

To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk

This is a preview from the server running through my markdig pipeline

ASP.NET Entity Framework

Hinzufügen des Entity Framework für Blog-Posts (Teil 2)

Thursday, 15 August 2024

Sie finden alle Quellcode für die Blog-Beiträge auf GitHub

Teil 2 der Reihe über das Hinzufügen von Entity Framework zu einem.NET Core-Projekt. Teil 1 kann gefunden werden Hierher.

Einleitung

Im vorherigen Beitrag haben wir die Datenbank und den Kontext für unsere Blog-Posts eingerichtet. In diesem Beitrag werden wir die Dienste hinzufügen, um mit der Datenbank zu interagieren.

Im nächsten Beitrag werden wir detailliert darlegen, wie diese Dienste jetzt mit den vorhandenen Controllern und Ansichten funktionieren.

Einrichtung

Wir haben jetzt eine BlogSetup-Erweiterungsklasse, die diese Dienste aufstellt. Dies ist eine Erweiterung von dem, was wir in Teil 1, wo wir die Datenbank und den Kontext einrichten.

  public static void SetupBlog(this IServiceCollection services, IConfiguration configuration)
    {
        var config = services.ConfigurePOCO<BlogConfig>(configuration.GetSection(BlogConfig.Section));
       services.ConfigurePOCO<MarkdownConfig>(configuration.GetSection(MarkdownConfig.Section));
        switch (config.Mode)
        {
            case BlogMode.File:
                services.AddScoped<IBlogService, MarkdownBlogService>();
                services.AddScoped<IBlogPopulator, MarkdownBlogPopulator>();
                break;
            case BlogMode.Database:
                services.AddDbContext<MostlylucidDbContext>(options =>
                {
                    options.UseNpgsql(configuration.GetConnectionString("DefaultConnection"));
                });
                services.AddScoped<IBlogService, EFBlogService>();
                services.AddScoped<IMarkdownBlogService, MarkdownBlogPopulator>();
                services.AddScoped<IBlogPopulator, EFBlogPopulator>();
                break;
        }
    }

Dies nutzt die einfache BlogConfig Klasse zu definieren, in welchem Modus wir uns befinden, entweder File oder Database......................................................................................................... Auf dieser Grundlage registrieren wir die Dienste, die wir benötigen.

  "Blog": {
    "Mode": "File"
  }
public class BlogConfig : IConfigSection
{
    public static string Section => "Blog";
    
    public BlogMode Mode { get; set; }
}

public enum BlogMode
{
    File,
    Database
}

Schnittstellen

Da ich sowohl die Datei als auch die Datenbank in dieser Anwendung unterstützen möchte (denn warum nicht! Ich habe einen Interface-basierten Ansatz verwendet, mit dem diese auf Basis von Config ausgetauscht werden können.

Wir haben drei neue Schnittstellen, IBlogService, IMarkdownBlogService und IBlogPopulator.

IBlogService

Dies ist die Hauptschnittstelle für den Blog-Service. Es enthält Methoden, um Beiträge, Kategorien und einzelne Beiträge zu erhalten.

public interface IBlogService
{
   Task<List<string>> GetCategories();
    Task<List<BlogPostViewModel>> GetPosts(DateTime? startDate = null, string category = "");
    
    Task<PostListViewModel> GetPostsByCategory(string category, int page = 1, int pageSize = 10, string language = BaseService.EnglishLanguage);
    
    Task<BlogPostViewModel?> GetPost(string slug, string language = "");
    
    Task<PostListViewModel> GetPagedPosts(int page = 1, int pageSize = 10, string language = BaseService.EnglishLanguage);
    
    Task<List<PostListModel>> GetPostsForLanguage(DateTime? startDate = null, string category = "", string language = BaseService.EnglishLanguage);
}

IMarkdownBlogService

Dieser Dienst wird von der EFlogPopulatorService beim ersten Start die Datenbank mit Beiträgen aus den Markdown-Dateien bevölkern.

public interface IMarkdownBlogService
{
    Task<List<BlogPostViewModel>> GetPages();
    
    Dictionary<string, List<String>> LanguageList();
}

Wie Sie sehen können, ist es ziemlich einfach und hat nur zwei Methoden, GetPages und LanguageList......................................................................................................... Diese werden verwendet, um die Markdown-Dateien zu verarbeiten und die Liste der Sprachen zu erhalten.

IBlogPopulator

Die BlogPopulatoren werden in unserer obigen Setup-Methode verwendet, um das Datenbank- oder statische Cache-Objekt (für das File-basierte System) mit Posts zu bevölkern.

  public static async Task PopulateBlog(this WebApplication app)
    {
        await using var scope = app.Services.CreateAsyncScope();
        var config = scope.ServiceProvider.GetRequiredService<BlogConfig>();
        if(config.Mode == BlogMode.Database)
        {
           var blogContext = scope.ServiceProvider.GetRequiredService<MostlylucidDbContext>();
           await blogContext.Database.MigrateAsync();
        }
    
        var context = scope.ServiceProvider.GetRequiredService<IBlogPopulator>();
        await context.Populate();
    }

Sie können sehen, dass dies eine Erweiterung auf WebApplication Mit config kann die Datenbank-Migration bei Bedarf ausgeführt werden (was auch die Datenbank erzeugt, wenn sie nicht existiert). Es ruft dann die konfigurierte IBlogPopulator Service, um die Datenbank zu bevölkern.

Das ist die Schnittstelle für diesen Service.

public interface IBlogPopulator
{
    Task Populate();
}

Durchführung

Ziemlich einfach, oder? Dies wird in den beiden MarkdownBlogPopulator und EFBlogPopulator Unterricht.

  • Markdown - hier rufen wir in die GetPages Methode und bevölkere den Cache.
  /// <summary>
    ///     The method to preload the cache with pages and Languages.
    /// </summary>
    public async Task Populate()
    {
        await PopulatePages();
    }

    private async Task PopulatePages()
    {
        if (GetPageCache() is { Count: > 0 }) return;
        Dictionary<(string slug, string lang), BlogPostViewModel> pageCache = new();
        var pages = await GetPages();
        foreach (var page in pages) pageCache.TryAdd((page.Slug, page.Language), page);
        SetPageCache(pageCache);
    }
  • EF - hier rufen wir in die IMarkdownBlogService um die Seiten zu erhalten und dann die Datenbank zu bevölkern.
    public async Task Populate()
    {
        var posts = await markdownBlogService.GetPages();
        var languages = markdownBlogService.LanguageList();

        var languageEntities = await EnsureLanguages(languages);
        await EnsureCategoriesAndPosts(posts, languageEntities);

        await context.SaveChangesAsync();
    }

Wir haben diese Funktionalität in Schnittstellen aufgeteilt, um den Code verständlicher und'segregiert' zu machen (wie in den SOLID-Prinzipien). Auf diese Weise können wir die auf der Konfiguration basierenden Dienste einfach austauschen.

Schlussfolgerung

Im nächsten Beitrag werden wir genauer auf die Implementierung der Controller und Views schauen, um diese Dienste zu nutzen.

logo

©2024 Scott Galloway