# Het 'Entity Framework' toevoegen voor Blog Posts (Part 5)

<!--category-- ASP.NET, Entity Framework -->
<datetime class="hidden">2024-08-18T01:20</datetime>

Zie delen [1](/blog/addingentityframeworkforblogpostspt1) en [2](/blog/addingentityframeworkforblogpostspt2) en [3](/blog/addingentityframeworkforblogpostspt3) en [4](/blog/addingentityframeworkforblogpostspt4) voor de vorige stappen.

# Inleiding

In eerdere delen hebben we behandeld hoe de database op te zetten, hoe onze controllers en aansigten zijn gestructureerd, hoe ons service werkte , en hoe je de database met een aantal begingegevens opbouwtM SK3 In deze deel zullen we de details over hoe de EF-gebaseerde diensten werken en hoe we ze kunnen gebruiken in ons controllersMSC5

Zoals gewoonlijk zie je hier alle bronnen voor op mijn GitHub. [Hier.](https://github.com/scottgal/mostlylucidweb/tree/main/Mostlylucid/Blog), in de meest duidelijke folder/BloggidsM SK2

[TOC]

# Blogdiensten

## Lêergebaseerde Diensten

Vroeger gebruikten we een `MarkdownBlogService` om onze blogposts en talen te krijgen. Deze dienst werd geïnjecteerd in onze controllers en aansigten. Deze service was een eenvoudige dienst die afteken-bestanden van disket las en ze terugvoerde als `BlogViewModels`.

Dit gebruikte een statisch woordenboek om de blogposts te houden en dan terugvoerde het resultaat van dat woordenboek.

```csharp
  public async Task<PostListViewModel> GetPagedPosts(int page = 1, int pageSize = 10, string language = EnglishLanguage)
    {
        var model = new PostListViewModel();
        var posts = GetPageCache().Where(x => x.Value.Language == language)
            .Select(x => GetListModel(x.Value)).ToList();
        model.Posts = posts.OrderByDescending(x => x.PublishedDate).Skip((page - 1) * pageSize).Take(pageSize).ToList();
        model.TotalItems = posts.Count();
        model.PageSize = pageSize;
        model.Page = page;
        return await Task.FromResult(model);
    }
```

Dit is de `GetPagedPosts` methode van de `MarkdownBlogService`. Deze methode haalt de blogposts uit de cache en geeft ze terug als een `PostListViewModel`.

Het gebruik van Files voor het opslaan van Markdown-bestanden is nog steeds een goede aanpak, het maakt het makkelijk om posten toe te voegen ( Ik stoor gewoon markdown- bestanden op de schijf en check ze in ) en hetMSC3 is gemakkelijk te beherenM SK4 Maar we willen de database gebruiken om de posten en talen op te slaan

```mermaid
flowchart LR
    A[Write New Markdown File] -->|Checkin To Github| B(Github Action Triggers) -->  C(Builds Docker Image) --> D(Watchtower Pulls new Image) --> E(Site Updated)
   
  
```

## EF-gebaseerde diensten

In de [Vorige deel]((/blog/addingentityframeworkforblogpostspt 4) Ik liet zien hoe we de database met de blogdata zaaidenM SK3 Dit updates elke keer dat we de dockercontainer herontplooien en herlaten.[Met behulp van de waarnemingstoren. ](blog/dockercompose)) We gebruikten een `EFBlogPopulator` Class om dit te doen.

Onze stroom ziet er zo uit.

```mermaid
   flowchart TD
    A[Write New Markdown File] -->|Checkin To Github| B(Github Action Triggers)
    B --> C(Builds Docker Image)
    C --> D(Watchtower Pulls new Image)
    D --> E{New Files Added?}
    E -->|Yes| F(Add File to Database)
    E -->|No| G(Skip Database Seeding)
    F --> H(Site Updated)
    G --> H(Site Updated)

```

Nu we de blogposts in onze database hebben, gebruiken we de `EFBlogService` om de implementatie voor uit te voeren. `IBlogService` interface:

```csharp
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 = MarkdownBaseService.EnglishLanguage);
    Task<BlogPostViewModel?> GetPost(string slug, string language = "");
    Task<PostListViewModel> GetPagedPosts(int page = 1, int pageSize = 10, string language = MarkdownBaseService.EnglishLanguage);
    
    Task<List<PostListModel>> GetPostsForLanguage(DateTime? startDate = null, string category = "", string language = MarkdownBaseService.EnglishLanguage);
}
```

Dit is de `IBlogService` interface. Dit is de interface die onze controllers gebruiken om de blogposts te krijgen. `EFBlogService` Die implementeert deze interface en gebruikt de `BlogContext` om de gegevens uit de database te krijgen.
Net als bij Out FileBased service [Bovenaan](#file-based-services) We kunnen posten krijgen per categorie, per taal, per datumM SK2 en gepoogd .

### `GetPostList`

```csharp
    private async Task<PostListViewModel> GetPostList(int count, List<BlogPostEntity> posts, int page, int pageSize)
    {
        var languages = await NoTrackingQuery().Select(x =>
                new { x.Slug, x.LanguageEntity.Name }
            ).ToListAsync();

        var postModels = new List<PostListModel>();

        foreach (var postResult in posts)
        {
            var langArr = languages.Where(x => x.Slug == postResult.Slug).Select(x => x.Name).ToArray();

            postModels.Add(postResult.ToListModel(langArr));
        }

        var postListViewModel = new PostListViewModel
        {
            Page = page,
            PageSize = pageSize,
            TotalItems = count,
            Posts = postModels
        };

        return postListViewModel;
    }
```

Hier gebruiken we onze gemeenschappelijke `PostsQuery` Maar we voegen er nog meer toe. `NoTrackingQuery` Het is een eenvoudige methode die een vraagbaar antwoord terugbrengt. `BlogPostEntity` Maar met `AsNoTrackingWithIdentityResolution` added. Dit betekent dat de entiteiten niet getrackd worden door de context en alleen gelezen worden.

```csharp
     protected IQueryable<BlogPostEntity> PostsQuery()=>Context.BlogPosts.Include(x => x.Categories)
        .Include(x => x.LanguageEntity);
     
         private IQueryable<BlogPostEntity> NoTrackingQuery() => PostsQuery().AsNoTrackingWithIdentityResolution();
```

Je kunt zien dat we ook de talen voor de posten krijgen en dan een `PostListViewModel` Het is een structuur die paging-informatie accepteert.`Page`, `PageSize` en `TotalItems`) en wordt teruggestuurd aan de controller

### `GetPost`

Onze belangrijkste methode is de `GetPost` De methode die een enkele post krijgt door zijn `Slug` en `Language`. Dit is een eenvoudige methode die de `PostsQuery` om de post te krijgen en dan terug te geven. `BlogPostViewModel`.
Je kunt zien dat het ook een optioneel systeem heeft. `Language` parameters die standaard zijn. `EnglishLanguage` Dat is een constante in ons systeem. `MarkdownBaseService` Klas.

```csharp
  public async Task<BlogPostViewModel?> GetPost(string slug, string language = "")
    {
        if (string.IsNullOrEmpty(language)) language =MarkdownBaseService.EnglishLanguage;
        var post = await NoTrackingQuery().FirstOrDefaultAsync(x => x.Slug == slug && x.LanguageEntity.Name == language);
        if (post == null) return null;
        var langArr = await GetLanguagesForSlug(slug);
        return post.ToPostModel(langArr);
    }
```

Dit gebruikt ook onze gemeenschappelijke methode. `GetLanguagesForSlug` Dit is een eenvoudige methode die de talen voor een post teruggeeft.

```csharp
    private async Task<List<string>> GetLanguagesForSlug(string slug)=> await NoTrackingQuery()
        .Where(x => x.Slug == slug).Select(x=>x.LanguageEntity.Name).ToListAsync();
```

### `GetPostsByCategory`

Deze methode krijgt de posten per categorie ( zoals ASP.NET & Het entiteitsraamwerk voor deze post `PostsQuery` om de posten te krijgen en ze te filteren volgens de categorie. Het geeft dan de posts terug als een `PostListViewModel`.

```csharp
    public async Task<PostListViewModel> GetPostsByCategory(string category, int page = 1, int pageSize = 10,
        string language = MarkdownBaseService.EnglishLanguage)
    {
        
        var count = await NoTrackingQuery()
            .Where(x => x.Categories.Any(c => c.Name == category) && x.LanguageEntity.Name == language).CountAsync();
        var posts = await PostsQuery()
            .Where(x => x.Categories.Any(c => c.Name == category) && x.LanguageEntity.Name == language)
            .Skip((page - 1) * pageSize)
            .Take(pageSize)
            .ToListAsync();

        var languages = await GetLanguagesForSlugs(posts.Select(x => x.Slug).ToList());
        var postListViewModel = new PostListViewModel
        {
            Page = page,
            PageSize = pageSize,
            TotalItems = count,
            Posts = posts.Select(x => x.ToListModel(
                languages.FirstOrDefault(entry => entry.Key == x.Slug).Value.ToArray())).ToList()
        };
        return postListViewModel;
    }
```

# In slotting:

Je kunt zien dat de EF-gebaseerde diensten een beetje complexer zijn dan de File Based-diensten, maar ze zijn flexibeler en kunnen worden gebruikt in complexere scenario's. We kunnen de ES-geBaseerde diensten gebruiken in onze controllers en aanzichten om de blogposts en talen te krijgen.
In de toekomst bouwen we op deze en voegen andere diensten toe, zoals inline-bewerking en commentaar.
We zullen ook kijken hoe we deze over meerdere systemen kunnen synchroniseren.