Back to "Προσθήκη Πλαίσιο Οντότητας για Δημοσιεύσεις στο Blog (PtΜSK1 ΜSK2"

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

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

Saturday, 17 August 2024

Δείτε τα μέρη 1 και 2 και 3 για τα προηγούμενα βήματα.

Εισαγωγή

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

Όπως πάντα μπορείτε να δείτε όλες τις πηγές για αυτό στο GitHub μου ΕΔΩ, στο MostlylucidΜSK1Blog φάκελο.

Καθίστε τη βάση δεδομένων

Στο προηγούμενο εδάφιο αναφέρθηκε πως Εισαγωγή και εγκατάσταση των υπηρεσιών. Σε αυτό το τμήμα θα γνωρίζουμε ότι η ' αναμένεται να καλύψει τον τρόπο με τον οποίο πρέπει να σπέρνονται οι βάσεις δεδομένων με ορισμένα αρχικά δεδομένα, ειδικότερα ότι η EFBlogPopulator κλάση. Αυτή η κατηγορία είναι εγγεγραμμένη ως υπηρεσία στην SetupBlog Μέθοδος επέκτασης.

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

Μπορείτε να δείτε αυτό στο Populate Η μέθοδος που καλούμε στο _markdownBlogService.GetPages() Αυτό τρέχει μέσα από τα αρχεία makrdown μας και κατοικεί ένα πλήθος BlogViewModels Περιέχει όλες τις δημοσιεύσεις. Στη συνέχεια κάνουμε το ίδιο για τις γλώσσες; ίσως αυτό φαίνεται στο δικό μας translated φάκελο για όλα τα μεταφρασμένα αρχεία μάρκας που δημιουργήσαμε χρησιμοποιώντας EasyNMT (see ΕΔΩ για το πώς κάνουμε αυτό το μέρος).

Προσθέτοντας τις γλώσσες

Στη συνέχεια καλούμε στο δικό μας EnsureLanguages μέθοδος που εξασφαλίζει ότι όλες οι γλώσσες βρίσκονται στη βάση δεδομένων.Αυτή είναι μια απλή μέθοδο που ελέγχει εάν η γλώσσα υπάρχει και αν δεν την προσθέτει στην βάση δεδομέναΜSK1

  private async Task<List<LanguageEntity>> EnsureLanguages(Dictionary<string, List<string>> languages)
    {
        var languageList = languages.SelectMany(x => x.Value).ToList();
        var currentLanguages = await Context.Languages.Select(x => x.Name).ToListAsync();

        var languageEntities = new List<LanguageEntity>();
        var enLang = new LanguageEntity { Name =MarkdownBaseService.EnglishLanguage };

        if (!currentLanguages.Contains(MarkdownBaseService.EnglishLanguage)) Context.Languages.Add(enLang);
        languageEntities.Add(enLang);

        foreach (var language in languageList)
        {
            if (languageEntities.Any(x => x.Name == language)) continue;

            var langItem = new LanguageEntity { Name = language };

            if (!currentLanguages.Contains(language)) Context.Languages.Add(langItem);

            languageEntities.Add(langItem);
        }

        await Context.SaveChangesAsync(); // Save the languages first so we can reference them in the blog posts
        return languageEntities;
    }

Σας αρέσει' αναμένεται να δείτε αυτό είναι πολύ απλό και απλά εξασφαλίζει ότι όλες οι γλώσσες που έχουμε από τις δημοσιεύσεις καταγραφής σημείων βρίσκονται στη βάση δεδομένων; ανακοινώθηκε και όπως καθορίσαμε ότι τα IDs δημιουργούνται αυτοματοποιημένα πρέπει να SaveChanges για να διασφαλιστεί ότι οι IDS παράγονται.

Προσθήκη κατηγοριών και δημοσιεύσεων

Στη συνέχεια καλούμε στο δικό μας EnsureCategoriesAndPosts μέθοδος που εξασφαλίζει ότι όλες οι κατηγορίες και τα μηνύματα βρίσκονται στη βάση δεδομένων.Αυτό είναι λίγο πιο περίπλοκο καθώς πρέπει να βεβαιωθείτε ότι οι κατηγορίες βρίσκονται στην βάση δεδομένα και στη συνέχεια πρέπει να διασφαλίσουμε ότι οι δημοσιεύσεις βρίσκονται στη βάση δεδομένων

    private async Task EnsureCategoriesAndPosts(
        IEnumerable<BlogPostViewModel> posts,
        List<LanguageEntity> languageEntities)
    {
        var languages = languageEntities.ToDictionary(x => x.Name, x => x);
        var currentPosts = await PostsQuery().ToListAsync();
        foreach (var post in posts)
        {
            var existingCategories = Context.Categories.Local.ToList();
            var currentPost =
                currentPosts.FirstOrDefault(x => x.Slug == post.Slug && x.LanguageEntity.Name == post.Language);
            await AddCategoriesToContext(post.Categories, existingCategories);
            existingCategories = Context.Categories.Local.ToList();
            await AddBlogPostToContext(post, languages[post.Language], existingCategories, currentPost);
        }
    }

Εδώ χρησιμοποιούμε το Σύνδεσμο.Κατηγορίες.Διαθέσιμο για την παρακολούθηση των κατηγοριών που προστίθενται επί του παρόντος στο πλαίσιο M SK2ΜSK3Συμμετείχε στη βάση δεδομένων κατά τη διάρκεια της SaveAsync Κάντε κλήση). Μπορείτε να δείτε ότι καλούμε στο PostsQuery Η μέθοδος της κατηγορίας βάσης μας, η οποία είναι μια απλή μέθοδο που επιστρέφει ένα απαιτητικό BlogPostEntity Έτσι μπορούμε να αναζητήσουμε τη βάση δεδομένων για τις δημοσιεύσεις.

  protected IQueryable<BlogPostEntity> PostsQuery()=>Context.BlogPosts.Include(x => x.Categories)
        .Include(x => x.LanguageEntity);
   

Προσθέτοντας τις κατηγορίες

Στη συνέχεια καλούμε στο AddCategoriesToContext μέθοδος που εξασφαλίζει ότι όλες οι κατηγορίες βρίσκονται στη βάση δεδομένων.Αυτή είναι μια απλή μέθοδο που ελέγχει εάν η κατηγορία υπάρχει και αν δεν την προσθέτει στην βάση δεδομέναΜSK1

    private async Task AddCategoriesToContext(
        IEnumerable<string> categoryList,
        List<CategoryEntity> existingCategories)
    {
        foreach (var category in categoryList)
        {
            if (existingCategories.Any(x => x.Name == category)) continue;

            var cat = new CategoryEntity { Name = category };

             await Context.Categories.AddAsync(cat);
        }
    }

Και πάλι αυτό ελέγχει αν η κατηγορία υπάρχει και εάν δεν το προσθέτει στη βάση δεδομένων.

Προσθήκη των Blog Posts

Στη συνέχεια καλούμε στο AddBlogPostToContext Η μέθοδος, αυτό καλεί στη συνέχεια στο EFBaseService για να αποθηκεύσετε την ανάρτηση στη βάση δεδομένων.

    private async Task AddBlogPostToContext(
        BlogPostViewModel post,
        LanguageEntity postLanguageEntity,
        List<CategoryEntity> categories,
        BlogPostEntity? currentPost)
    {
        await SavePost(post, currentPost, categories, new List<LanguageEntity> { postLanguageEntity });
    }

Αυτό το κάνουμε κάνοντας την SavePost Μέθοδος η οποία είναι μια μέθοδος που αποθηκεύει την ανάρτηση στη βάση δεδομένων.Αυτή η μέθοδο είναι λίγο περίπλοκη καθώς πρέπει να ελέγξει εάν η ανάρτηση έχει αλλάξει και αν έτσι επικαιροποιήσει τη ανάρτηση στην βάση δεδομένα.


   public async Task<BlogPostEntity?> SavePost(BlogPostViewModel post, BlogPostEntity? currentPost =null ,
        List<CategoryEntity>? categories = null,
        List<LanguageEntity>? languages = null)
    {
        if (languages == null)
            languages = await Context.Languages.ToListAsync();

    var postLanguageEntity = languages.FirstOrDefault(x => x.Name == post.Language);
        if (postLanguageEntity == null)
        {
            Logger.LogError("Language {Language} not found", post.Language);
            return null;
        }
        categories ??= await Context.Categories.Where(x => post.Categories.Contains(x.Name)).ToListAsync();
         currentPost ??= await PostsQuery().Where(x=>x.Slug == post.Slug).FirstOrDefaultAsync();
        try
        {
            var hash = post.HtmlContent.ContentHash();
            var currentCategoryNames = currentPost?.Categories.Select(x => x.Name).ToArray() ?? Array.Empty<string>();
            var categoriesChanged = false;
            if (!currentCategoryNames.All(post.Categories.Contains) ||
                !post.Categories.All(currentCategoryNames.Contains))
            {
                categoriesChanged = true;
                Logger.LogInformation("Categories have changed for post {Post}", post.Slug);
            }

            var dateChanged = currentPost?.PublishedDate.UtcDateTime.Date != post.PublishedDate.ToUniversalTime().Date;
            var titleChanged = currentPost?.Title != post.Title;
            if (!titleChanged && !dateChanged && hash == currentPost?.ContentHash && !categoriesChanged)
            {
                Logger.LogInformation("Post {Post} has not changed", post.Slug);
                return currentPost;
            }

            
            var blogPost = currentPost ?? new BlogPostEntity();
            
            blogPost.Title = post.Title;
            blogPost.Slug = post.Slug;
            blogPost.OriginalMarkdown = post.OriginalMarkdown;
            blogPost.HtmlContent = post.HtmlContent;
            blogPost.PlainTextContent = post.PlainTextContent;
            blogPost.ContentHash = hash;
            blogPost.PublishedDate = post.PublishedDate;
            blogPost.LanguageEntity = postLanguageEntity;
            blogPost.Categories = categories.Where(x => post.Categories.Contains(x.Name)).ToList();

            if (currentPost != null)
            {
                Logger.LogInformation("Updating post {Post}", post.Slug);
                Context.BlogPosts.Update(blogPost); // Update the existing post
            }
            else
            {
                Logger.LogInformation("Adding new post {Post}", post.Slug);
                Context.BlogPosts.Add(blogPost); // Add a new post
            }
            return blogPost;
        }
        catch (Exception e)
        {
            Logger.LogError(e, "Error adding post {Post}", post.Slug);
        }

        return null;
    }

Όπως μπορείτε να δείτε αυτό έχει ένα LOT της ανίχνευσης αλλαγών για να βεβαιωθείτε ότι δεν κάνουμε'τ επανειλημμένα-add posts που έχουν'τ αλλάξειΜSK3Εμείς ελέγξουμε το hash του περιεχομένου, τις κατηγορίεςM SK5 την ημερομηνία και τον τίτλοMK6Αν οποιοδήποτε από αυτά έχουν αλλάξει ενημερώνουμε το post στη βάση δεδομένων

Ένα πράγμα που πρέπει να σημειωθεί είναι το πόσο ενοχλητικό είναι να ελέγξετε ένα DateTimeOffset είναι; θα πρέπει να το μετατρέψουμε σε UTC και στη συνέχεια να πάρετε την ημερομηνία για να το συγκρίνετεΜSK1 Αυτό οφείλεται στο γεγονός ότι η DateTimeOffset έχει ένα στοιχείο χρόνου και θέλουμε να συγκρίνουμε μόνο την ημερομηνία.

var dateChanged = currentPost?.PublishedDate.UtcDateTime.Date != post.PublishedDate.ToUniversalTime().Date;

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

Τώρα έχουμε ένα πλήρως λειτουργικό σύστημα blog που μπορεί να λαμβάνεται από αρχεία μάρκινγκ και μεταφρασμένα αρχεία Μάρκίνγκ. Στο επόμενο μέρος θα καλύψουμε την απλή Υπηρεσία που χρησιμοποιούμε για την προβολή δημοσιεύσεων που αποθηκεύονται στη βάση δεδομένων ΜΚ2

logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.