# Προσθήκη Πλαίσιο Οντότητας για Δημοσιεύσεις στο Blog (Παρουσίαση ΜSK1

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

Δείτε τα μέρη [1](/blog/addingentityframeworkforblogpostspt1) και [2](/blog/addingentityframeworkforblogpostspt2) και [3](/blog/addingentityframeworkforblogpostspt3) και [4](/blog/addingentityframeworkforblogpostspt4) για τα προηγούμενα βήματα.

# Εισαγωγή

Σε προηγούμενα μέρη, καλύπτουμε πώς να δημιουργήσουμε τη βάση δεδομένων,Πώς διαρθρώνονται οι ελεγκτές και οι απόψεις μαςΜSK1Πως λειτουργούν οι υπηρεσίες μας, και πώς να δούμε την βάση δεδομένα με ορισμένα αρχικά δεδομέναM SK3Σε αυτό το μέρος θα γνωρίζουμε'περιλαμβάνουμε λεπτομέρειες σχετικά με τον τρόπο λειτουργίας των υπηρεσιών EF Based και πώς μπορούμε να τις χρησιμοποιήσουμε στους εταίρους μας ΜSK5

Όπως πάντα μπορείτε να δείτε όλες τις πηγές για αυτό στο GitHub μου [ΕΔΩ](https://github.com/scottgal/mostlylucidweb/tree/main/Mostlylucid/Blog), στο MostlylucidΜSK1Blog φάκελο.

[TOC]

# Blog Υπηρεσίες

## Υπηρεσίες βάσει αρχείων

Προηγουμένως χρησιμοποιούσαμε ένα `MarkdownBlogService` για να πάρετε τα άρθρα και τις γλώσσες του blog μας.Αυτή η υπηρεσία έχει ενσωματωθεί στους ελεγκτές και τις προβολές μαςΜSK1Η υπηρεσία αυτή ήταν μια απλή υπηρεσία που διαβάζει αρχεία καταγραφής από τον δίσκο και τους επιστρέφει ως `BlogViewModels`.

Αυτό χρησιμοποίησε ένα στατικό λεξικό για να κρατήσει τα μηνύματα στο blog και στη συνέχεια επέστρεψε αποτελέσματα από αυτό το Λεξικό.

```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);
    }
```

Αυτό είναι το `GetPagedPosts` Μέθοδος από την `MarkdownBlogService`. Αυτή η μέθοδος λαμβάνει τα μηνύματα του blog από το cache και τα επιστρέφει ως `PostListViewModel`.

Χρησιμοποιώντας αρχεία για την αποθήκευση των αρχείων Markdown είναι ακόμα μια καλή προσέγγιση, αν και καθιστά εύκολο να προσθέσετε τις δημοσιεύσεις ΜSK1 αν και απλά αποθηκεύετε τα αρχεία markdown στον δίσκο και ελέγξτε τα σε) αν και αυτό σημαίνει ότι το ' μπορεί να διαχειριστεί εύκολαM SK4 αν και θέλουμε να χρησιμοποιήσουμε τη βάση δεδομένων για να αποθηκευτούν οι αναφορές και οι γλώσσεςMK5 αν και

```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

Στον [προηγούμενο κομμάτι]((/blog/addingentityframeworkforblogpostsptΜSK2 έδειξα πώς κρεμασθήκαμε τη βάση δεδομένων με τα δεδομένα του blogM SK3Αυτή η ενημέρωση κάθε φορά που επανεκτείνουμε και επαναφέραμε το δοχείο MK4[Χρησιμοποιώντας το Watchtower ](blog/dockercompose)) Χρησιμοποιήσαμε ένα `EFBlogPopulator` Η τάξη για να το κάνεις αυτό.

Τώρα η ροή μας μοιάζει

```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)

```

Τώρα που έχουμε τα μηνύματα στο blog στη βάση δεδομένων μας χρησιμοποιούμε το `EFBlogService` Για να εξασφαλιστεί η υλοποίηση `IBlogService` Διασύνδεση:

```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);
}
```

Αυτό είναι το `IBlogService` interface.Αυτή είναι η διεπαφή που χρησιμοποιούν οι ελεγκτές μας για να λάβουν τα άρθρα του blog. `EFBlogService` Εφαρμόστε αυτή τη διεπαφή και χρησιμοποιήστε την `BlogContext` Για να αποκτήσετε τα δεδομένα από τη βάση δεδομένων.
Όπως και η υπηρεσία FileBased [Πάνω](#file-based-services) Μπορούμε να λαμβάνουμε δημοσιεύσεις ανά κατηγορία, με γλώσσαMST1 με ημερομηνίαMSS2 και pagedMSM3

### `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;
    }
```

Εδώ χρησιμοποιούμε το κοινό μας `PostsQuery` Εμείς προσθέτουμε `NoTrackingQuery` που είναι μια απλή μέθοδος η οποία επιστρέφει ένα επιθυμητό από το `BlogPostEntity` Αλλά με `AsNoTrackingWithIdentityResolution` προσθέτει. Αυτό σημαίνει ότι οι οντότητες δεν παρακολουθούνται από το πλαίσιο και διαβάζονται μόνοΜSK1 Αυτό είναι χρήσιμο όταν απλά διαβάζουμε τα δεδομένα και δεν την ενημερώνουμε

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

Μπορείτε να δείτε ότι έχουμε επίσης τις γλώσσες για τα posts και στη συνέχεια δημιουργήστε ένα `PostListViewModel` η οποία είναι μια δομή που αποδέχεται πληροφόρηση (`Page`, `PageSize` και `TotalItems`) αναφέρθηκε και επιστρέφεται στον ελεγκτή ΜSK1 αναφέρθηκαν

### `GetPost`

Η κύρια μέθοδος μας είναι η `GetPost` Μέθοδος που λαμβάνει ένα ενιαίο post από το `Slug` και `Language`. Αυτή είναι μια απλή μέθοδος που χρησιμοποιεί την `PostsQuery` να πάρει το μήνυμα και στη συνέχεια επιστρέφει ως `BlogPostViewModel`.
Μπορείτε να δείτε ότι έχει επίσης μια προαιρετική `Language` παραμέτρων που υποχωρούν σε `EnglishLanguage` Η οποία είναι σταθερή στην `MarkdownBaseService` ΕΠΙΧΕΙΡΕΥΣΗ ΚΟΙΝΩΝΙΑ

```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);
    }
```

Χρησιμοποιεί επίσης την κοινή μας μέθοδο. `GetLanguagesForSlug` που παίρνει τις γλώσσες για ένα post.Αυτή είναι μια απλή μέθοδος που επιστρέφει τις γλώσσα για ένα PostΜSK1

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

### `GetPostsByCategory`

Αυτή η μέθοδος λαμβάνει τις δημοσιεύσεις ανά κατηγορία (like ASP.NET ΜSK2 Entity Framework για αυτή την ανάρτησηM SK3 Χρησιμοποιεί το `PostsQuery` για να πάρετε τις δημοσιεύσεις και στη συνέχεια τις φιλτράρει με την κατηγορία. Στη συνέχεια επιστρέφει τις αναρτήσεις ως `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;
    }
```

# Στο συμπέρασμα

Μπορείτε να δείτε ότι οι Υπηρεσίες με βάση το EF είναι λίγο πιο περίπλοκες από τις υπηρεσίες με βάση τα αρχεία, αλλά είναι πιο ευέλικτες και μπορούν να χρησιμοποιηθούν σε πιο σύνθετα σενάρια.Μπορούμε να χρησιμοποιήσουμε τις Υπηρετήσεις με βάση τον EF στους ελεγκτές μας και στις προβολές για να λάβουμε τις δημοσιεύσεις στο blog και τις γλώσσες.
Στο μέλλον θα χτίσουμε το ' και θα προσθέσουμε υπηρεσίες όπως η επεξεργασία σε απευθείας σύνδεση και τα σχόλια στο .
Θα εξετάσουμε επίσης πώς θα μπορούσαμε να συγχρονίσουμε αυτά τα συστήματα σε διάφορα συστήματα.