{"id":25448878,"url":"https://github.com/shadyashraf174/blog","last_synced_at":"2026-04-22T23:35:25.342Z","repository":{"id":277897577,"uuid":"933849658","full_name":"shadyashraf174/Blog","owner":"shadyashraf174","description":"A C# console app using Entity Framework Core to query blog data. It calculates comments per user, posts by last comment date, and \"last comments\" per user. Uses an in-memory SQLite database with clean console output.","archived":false,"fork":false,"pushed_at":"2025-02-16T20:42:59.000Z","size":12,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-16T08:09:27.640Z","etag":null,"topics":["console-app","csharp","data-queries","ef-core","linq","net-7","sqlite"],"latest_commit_sha":null,"homepage":"https://github.com/Shaddix/Blog/blob/master/Program.cs#L24-L54","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shadyashraf174.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-02-16T20:30:43.000Z","updated_at":"2025-02-16T20:50:28.000Z","dependencies_parsed_at":"2025-02-16T21:37:37.422Z","dependency_job_id":null,"html_url":"https://github.com/shadyashraf174/Blog","commit_stats":null,"previous_names":["shadyashraf174/blog"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shadyashraf174%2FBlog","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shadyashraf174%2FBlog/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shadyashraf174%2FBlog/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shadyashraf174%2FBlog/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shadyashraf174","download_url":"https://codeload.github.com/shadyashraf174/Blog/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254493384,"owners_count":22080127,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["console-app","csharp","data-queries","ef-core","linq","net-7","sqlite"],"created_at":"2025-02-17T20:15:27.372Z","updated_at":"2026-04-22T23:35:25.294Z","avatar_url":"https://github.com/shadyashraf174.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# Blog Application\n\nThis is a console application built using **C#** and **Entity Framework Core** that demonstrates querying data from a blog context. The application calculates and displays three specific metrics related to blog posts and comments:\n\n1. **How many comments each user left.**\n2. **Posts ordered by the date of the last comment.**\n3. **How many \"last comments\" each user left (where \"last comment\" is the latest comment in each post).**\n\nThe application uses an in-memory SQLite database for simplicity and ensures clean console output without verbose logging.\n\n---\n\n## Table of Contents\n\n- [Overview](#overview)\n- [Prerequisites](#prerequisites)\n- [Setup Instructions](#setup-instructions)\n- [Database Setup](#database-setup)\n- [How to Run](#how-to-run)\n- [Expected Output](#expected-output)\n- [Code Structure](#code-structure)\n- [Technical Details](#technical-details)\n- [Suppressing Logs](#suppressing-logs)\n- [Query](#Query)\n\n---\n\n## Overview\n\nThe application initializes an in-memory SQLite database with sample data, performs LINQ queries to calculate the required metrics, and outputs the results to the console. It ensures clean and concise output by disabling unnecessary logging.\n\n---\n\n## Prerequisites\n\nBefore running the application, ensure you have the following installed on your machine:\n\n- [.NET SDK](https://dotnet.microsoft.com/download) (version 7.0 or later)\n- A text editor or IDE (e.g., Visual Studio Code, Visual Studio)\n\n---\n\n## Setup Instructions\n\n1. **Clone the Repository:**\n   \n   ```bash\n   git clone https://github.com/shadyashraf174/Blog.git\n   ```\n---\n\n## Database Setup\n\nThe application uses an in-memory SQLite database for simplicity. The database schema consists of two entities:\n\n1. **BlogPost**:\n   - `Id`: Unique identifier for the blog post.\n   - `Title`: Title of the blog post.\n   - `Text`: Content of the blog post.\n   - `Comments`: A collection of `BlogComment` objects associated with the post.\n\n2. **BlogComment**:\n   - `Id`: Unique identifier for the comment.\n   - `Text`: Content of the comment.\n   - `CreatedDate`: Date and time when the comment was created.\n   - `UserName`: Name of the user who left the comment.\n   - `BlogPostId`: Foreign key referencing the associated `BlogPost`.\n\nThe database is initialized with sample data in the `InitializeData` method of the `Program` class.\n\n---\n\n## How to Run\n\nTo run the application, execute the following command in the terminal:\n```bash\ndotnet run\n```\n\nThe program will output the results of the three queries to the console.\n\n---\n\n## Expected Output\n\nWhen the program runs successfully, you should see the following clean output:\n\n```\nHello World!\nHow many comments each user left:\nIvan: 4\nPetr: 2\nElena: 3\nPosts ordered by date of last comment:\nPost2: '2020-03-06'\nPost1: '2020-03-05'\nPost3: '2020-02-14'\nHow many last comments each user left:\nIvan: 2\nPetr: 1\n[\"Post1\",\"Post2\",\"Post3\"]\n```\n\n---\n\n## Code Structure\n\n### **1. `BlogComment` Class**\nRepresents a comment entity with properties for `Id`, `Text`, `CreatedDate`, `UserName`, and `BlogPostId`.\n\n### **2. `BlogPost` Class**\nRepresents a blog post entity with properties for `Id`, `Title`, `Text`, and a collection of `BlogComment` objects.\n\n### **3. `MyDbContext` Class**\nDefines the database context and configures the in-memory SQLite database.\n\n### **4. `Program` Class**\nContains the main logic of the application, including:\n- Initialization of the database with sample data.\n- Execution of the three LINQ queries.\n- Output of the results to the console.\n\n---\n\n## Technical Details\n\n### **1. Entity Framework Core**\n- Used for ORM (Object-Relational Mapping) and database operations.\n- Configured to use an in-memory SQLite database for simplicity.\n\n### **2. LINQ Queries**\n- **Query 1**: Flattens the list of comments from all posts, groups them by `UserName`, and counts the number of comments per user.\n- **Query 2**: Finds the maximum `CreatedDate` for each post's comments and orders the posts by this date in descending order.\n- **Query 3**: Identifies the latest comment for each post, groups these \"last comments\" by `UserName`, and counts the number of last comments per user.\n\n### **3. Logging**\n- Uses `Microsoft.Extensions.Logging.Console` for logging.\n- Logging is configured to suppress informational messages (e.g., SQL commands) and display only warnings or higher-level logs.\n\n---\n\n## Suppressing Logs\n\nTo ensure clean console output without verbose logging, the `LoggerFactory` is configured as follows:\n\n```csharp\nvar loggerFactory = LoggerFactory.Create(builder =\u003e\n{\n    builder.AddConsole(); // Enable console logging\n    builder.SetMinimumLevel(LogLevel.Warning); // Suppress info-level logs\n});\n```\n\nThis configuration disables informational logs such as SQL commands and other detailed messages, resulting in a cleaner output.\n\n---\n\nBelow is a detailed explanation of the three LINQ queries implemented in your project. Each query is designed to calculate specific metrics related to blog posts and comments, and I'll break down how they work step by step.\n\n---\n## Query\n\n### **Query 1: How many comments each user left?**\n\n#### **Purpose**\nThis query calculates the total number of comments left by each user across all blog posts.\n\n#### **Code**\n```csharp\nvar commentsPerUser = context.BlogPosts\n    .SelectMany(post =\u003e post.Comments) // Flatten the list of comments from all posts\n    .GroupBy(comment =\u003e comment.UserName) // Group comments by UserName\n    .Select(group =\u003e new {\n        UserName = group.Key, // The user's name\n        CommentCount = group.Count() // Count the number of comments for this user\n    })\n    .ToList();\n```\n\n#### **Explanation**\n1. **`SelectMany(post =\u003e post.Comments)`**:\n   - This flattens the nested collections of comments from all blog posts into a single enumerable.\n   - Instead of working with a collection of collections (`IEnumerable\u003cIEnumerable\u003cBlogComment\u003e\u003e`), it creates a single `IEnumerable\u003cBlogComment\u003e`.\n\n2. **`GroupBy(comment =\u003e comment.UserName)`**:\n   - Groups the flattened list of comments by the `UserName` property.\n   - This groups all comments made by the same user together.\n\n3. **`Select(group =\u003e new { ... })`**:\n   - For each group of comments (one group per user), it creates an anonymous object containing:\n     - `UserName`: The name of the user.\n     - `CommentCount`: The total number of comments made by that user.\n\n4. **`ToList()`**:\n   - Converts the result into a list for easier iteration and output.\n\n#### **Output**\nThe result is a list of objects, where each object contains:\n- `UserName`: The name of the user.\n- `CommentCount`: The total number of comments left by that user.\n\nExample Output:\n```\nIvan: 4\nPetr: 2\nElena: 3\n```\n\n---\n\n### **Query 2: Posts ordered by the date of the last comment**\n\n#### **Purpose**\nThis query determines the latest comment for each blog post and orders the posts by this date in descending order.\n\n#### **Code**\n```csharp\nvar postsOrderedByLastComment = context.BlogPosts\n    .Select(post =\u003e new {\n        PostTitle = post.Title, // The title of the blog post\n        LastCommentDate = post.Comments.Max(comment =\u003e comment.CreatedDate) // Find the latest comment's date\n    })\n    .OrderByDescending(post =\u003e post.LastCommentDate) // Order posts by the latest comment date (descending)\n    .ToList();\n```\n\n#### **Explanation**\n1. **`Select(post =\u003e new { ... })`**:\n   - For each blog post, it creates an anonymous object containing:\n     - `PostTitle`: The title of the blog post.\n     - `LastCommentDate`: The latest comment's `CreatedDate` for this post, calculated using `Max(comment =\u003e comment.CreatedDate)`.\n\n2. **`OrderByDescending(post =\u003e post.LastCommentDate)`**:\n   - Orders the posts based on the `LastCommentDate` in descending order, so the post with the most recent comment appears first.\n\n3. **`ToList()`**:\n   - Converts the result into a list for easier iteration and output.\n\n#### **Output**\nThe result is a list of objects, where each object contains:\n- `PostTitle`: The title of the blog post.\n- `LastCommentDate`: The date of the latest comment for that post.\n\nExample Output:\n```\nPost2: '2020-03-06'\nPost1: '2020-03-05'\nPost3: '2020-02-14'\n```\n\n---\n\n### **Query 3: How many last comments each user left?**\n\n#### **Purpose**\nThis query identifies the latest comment for each blog post, groups these \"last comments\" by the user who made them, and counts the number of last comments per user.\n\n#### **Code**\n```csharp\nvar lastCommentsPerUser = context.BlogPosts\n    .Select(post =\u003e post.Comments\n        .OrderByDescending(comment =\u003e comment.CreatedDate) // Sort comments by CreatedDate (descending)\n        .FirstOrDefault()) // Take the latest comment for this post\n    .Where(comment =\u003e comment != null) // Filter out any null values (posts without comments)\n    .GroupBy(comment =\u003e comment.UserName) // Group the latest comments by UserName\n    .Select(group =\u003e new {\n        UserName = group.Key, // The user's name\n        LastCommentCount = group.Count() // Count the number of last comments for this user\n    })\n    .ToList();\n```\n\n#### **Explanation**\n1. **`Select(post =\u003e post.Comments.OrderByDescending(...).FirstOrDefault())`**:\n   - For each blog post, it sorts the comments by `CreatedDate` in descending order and selects the latest comment using `FirstOrDefault()`.\n   - If a post has no comments, `FirstOrDefault()` will return `null`.\n\n2. **`Where(comment =\u003e comment != null)`**:\n   - Filters out any `null` values (i.e., posts without comments).\n\n3. **`GroupBy(comment =\u003e comment.UserName)`**:\n   - Groups the latest comments by the `UserName` property.\n   - This groups all \"last comments\" made by the same user together.\n\n4. **`Select(group =\u003e new { ... })`**:\n   - For each group of comments (one group per user), it creates an anonymous object containing:\n     - `UserName`: The name of the user.\n     - `LastCommentCount`: The total number of last comments made by that user.\n\n5. **`ToList()`**:\n   - Converts the result into a list for easier iteration and output.\n\n#### **Output**\nThe result is a list of objects, where each object contains:\n- `UserName`: The name of the user.\n- `LastCommentCount`: The total number of last comments made by that user.\n\nExample Output:\n```\nIvan: 2\nPetr: 1\n```\n\n---\n\n### **Summary of Queries**\n\n| Query Number | Metric Calculated                                                                 | Key Operations Used                                                                 |\n|--------------|-----------------------------------------------------------------------------------|-------------------------------------------------------------------------------------|\n| **Query 1**  | Total number of comments per user.                                               | `SelectMany`, `GroupBy`, `Count`                                                    |\n| **Query 2**  | Blog posts ordered by the date of their latest comment.                          | `Select`, `Max`, `OrderByDescending`                                                |\n| **Query 3**  | Total number of \"last comments\" per user (latest comment per post).              | `OrderByDescending`, `FirstOrDefault`, `Where`, `GroupBy`, `Count`                  |\n\nThese queries demonstrate the power of LINQ in processing complex data relationships and calculating meaningful insights from the database. Each query is efficient, concise, and leverages LINQ's ability to transform and aggregate data seamlessly.\n\n---\n![image](https://github.com/user-attachments/assets/1b0902ed-545c-4169-a672-135a87147e67)\n\n---\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshadyashraf174%2Fblog","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshadyashraf174%2Fblog","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshadyashraf174%2Fblog/lists"}