NOTE: Apart from
(and even then it's questionable, I'm Scottish). These are machine translated in languages I don't read. If they're terrible please contact me.
You can see how this translation was done in this article.
Thursday, 15 August 2024
//Less than a minute
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.
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.
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
}
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
.
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);
}
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.
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();
}
Ziemlich einfach, oder? Dies wird in den beiden MarkdownBlogPopulator
und EFBlogPopulator
Unterricht.
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);
}
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.
Im nächsten Beitrag werden wir genauer auf die Implementierung der Controller und Views schauen, um diese Dienste zu nutzen.