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
ब्लॉग पोस्ट के लिए एंटिटी फ्रेमवर्क जोड़ना (Pt.
Saturday, 17 August 2024
भाग देखें 1 और 2 और 3 पिछले चरणों के लिए
परिचय
पिछले भागों में हमने डेटाबेस को कैसे स्थापित करना शामिल किया है-,, कैसे हमारे नियंत्रक और दृश्य संरचना हैं-, & #44; और कैसे हमारी सेवाओं का काम करता है।
जैसा कि आमतौर पर आप इस के लिए सभी स्रोत मेरी GitHub पर देख सकते हैं यहाँMostlylucid में ,Blog फ़ोल्डर
डाटाबेस की बीजिंग
पिछले भाग में हम कैसे हम सेवाओं को आरंभ और सेटअप करें. इस भाग में हम'\हम कैसे कुछ प्रारंभिक डेटा के साथ डाटाबेस को बीजित करने के लिए कवर करते हैं 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 फ़ाइलों के माध्यम से चलाता है और एक गुच्छा populates BlogViewModels सभी पदों को समाहित
तब हम भाषाओं के लिए ऐसा ही करते हैं; यह हमारी ओर देखता है translated सभी अनुवादित मार्कडाउन फ़ाइलों के लिए फ़ोल्डर जो हमने EasyNMT (से बनाया है यहाँ कैसे हम उस भाग को करते हैं के लिए
भाषाएँ जोड़ें
फिर हम अपने में बुलाते हैं EnsureLanguages विधि जो यह सुनिश्चित करता है कि सभी भाषाएँ डाटाबेस में हैं
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;
}
आप 'll देखेंगे यह ppretty सरल है और सिर्फ सुनिश्चित करता है कि सभी भाषाओं हम Markdown पदों से प्राप्त हैं डेटाबेस में हैं 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);
}
}
यहाँ हम कंटेक्स्ट का उपयोग करते हैं Context.Categories.Local वर्तमान में कंटेक्ट में जोड़े गए वर्गों को ट्रैक करने के लिए SaveAsync कॉल
आप देख सकते हैं कि हम में कॉल PostsQuery हमारे आधार वर्ग की विधि जो एक सरल विधि है कि एक क्वेरी करने योग्य के वापस करता है BlogPostEntity तो हम पोस्टों के लिए डाटाबेस क्वेरी कर सकते हैं
protected IQueryable<BlogPostEntity> PostsQuery()=>Context.BlogPosts.Include(x => x.Categories)
.Include(x => x.LanguageEntity);
वर्ग जोड़ें
फिर हम में बुलाते हैं AddCategoriesToContext विधि जो सुनिश्चित करता है कि सभी श्रेणी डाटाबेस में हैं
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);
}
}
यह फिर से जाँच करता है कि क्या श्रेणी मौजूद है और यदि नहीं यह डाटाबेस में जोड़ता है
ब्लॉग पोस्ट्स जोड़ें
फिर हम में बुलाते हैं 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 है सुनिश्चित करने के लिए हम नहीं कर रहे हैं।
ध्यान देने के लिए एक बात यह है कि कैसे एक DateTimeOffset की जाँच करने में परेशानी है हम इसे यूटीसी में रूपांतरित करना चाहते हैं और फिर इसे तुलना करने के लिए तिथि प्राप्त करें। DateTimeOffset एक समय घटक है और हम सिर्फ तारीख को तुलना करना चाहते हैं
var dateChanged = currentPost?.PublishedDate.UtcDateTime.Date != post.PublishedDate.ToUniversalTime().Date;
अंत में
अब हम एक पूरी तरह से काम कर रहे ब्लॉग सिस्टम है जो मार्कडाउन फ़ाइलों और अनुवादित मार्कडॉन फ़ाइलें से populated किया जा सकता है