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
U vindt alle broncode voor de blog berichten op GitHub
Deel 2 van de reeks over het toevoegen van Entity Framework aan een.NET Core project. Deel 1 is te vinden Hier..
In de vorige post, zetten we de database en de context voor onze blog berichten. In deze post, zullen we de diensten toe te voegen om te communiceren met de database.
In de volgende post zullen we detailleren hoe deze diensten nu werken met de bestaande controllers en meningen.
We hebben nu een BlogSetup uitbreidingsklasse die deze diensten instelt. Dit is een uitbreiding van wat we deden in Deel 1, waar we de database en context opzetten.
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;
}
}
Dit maakt gebruik van de eenvoudige BlogConfig
klasse om te bepalen in welke modus we zitten, ofwel File
of Database
. Op basis hiervan registreren we de diensten die we nodig hebben.
"Blog": {
"Mode": "File"
}
public class BlogConfig : IConfigSection
{
public static string Section => "Blog";
public BlogMode Mode { get; set; }
}
public enum BlogMode
{
File,
Database
}
Omdat ik zowel het bestand als de Database in deze toepassing wil ondersteunen (omdat waarom niet! Ik heb gebruik gemaakt van een interface gebaseerde aanpak waardoor deze kunnen worden verwisseld op basis van config.
We hebben drie nieuwe interfaces. IBlogService
, IMarkdownBlogService
en IBlogPopulator
.
Dit is de belangrijkste interface voor de blog service. Het bevat methoden voor het verkrijgen van posten, categorieën en individuele posten.
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);
}
Deze dienst wordt gebruikt door de EFlogPopulatorService
op de eerste run om de database te vullen met berichten uit de markdown bestanden.
public interface IMarkdownBlogService
{
Task<List<BlogPostViewModel>> GetPages();
Dictionary<string, List<String>> LanguageList();
}
Zoals je kunt zien is het vrij eenvoudig en heeft slechts twee methoden, GetPages
en LanguageList
. Deze worden gebruikt om de Markdown-bestanden te verwerken en de lijst met talen te krijgen.
De BlogPopulators worden gebruikt in onze setup methode hierboven om de database of statische cache object (voor het op bestanden gebaseerde systeem) met berichten te bevolken.
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();
}
U kunt zien dat dit een uitbreiding is naar WebApplication
met config waarmee de Database Migration kan worden uitgevoerd indien nodig (die ook de Database aanmaakt als deze niet bestaat). Het noemt dan de geconfigureerde IBlogPopulator
service om de database te vullen.
Dit is de interface voor die dienst.
public interface IBlogPopulator
{
Task Populate();
}
Vrij simpel toch? Dit wordt ten uitvoer gelegd in zowel de Lid-Staten als in de Lid-Staten van de Gemeenschap. MarkdownBlogPopulator
en EFBlogPopulator
Lessen.
GetPages
methode en bevolk de 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
om de pagina's te krijgen en vervolgens de database te bevolken. 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();
}
We hebben deze functionaliteit opgedeeld in interfaces om de code begrijpelijker en 'gescheiden' te maken (zoals in de SOLID principes). Dit stelt ons in staat om eenvoudig de diensten te ruilen op basis van de configuratie.
In de volgende post zullen we meer in detail kijken naar de implementatie van de Controllers en Views om deze diensten te gebruiken.