locked
[EF Core] Find an entity with a string field ? RRS feed

  • Question

  • User-1370514677 posted

    Hi everyone,

    Is there a way to find an entity with a string field instead of its Id ? Or at least find an enity's Id from one of its fields ?

    Indeed I'd like to achieve the following :

            [HttpGet]
            public async Task<IActionResult> GetArticleCategoryImage(int Id)
            {
                var current_article = await _articleContext.Article.FindAsync(Id);
                
                // var category_id = find id with this key : current_article.CategoryName (string)
                var article_category = await _articleContext.Category.FindAsync(current_article.CategoryName);
    
                var ImageFile = article_category.Image;
    
                return File(ImageFile,"image/svg+xml");
            }

    Article.cs

    using System.ComponentModel.DataAnnotations;
    
    namespace DevAstuces.Models
    {
        public class Article
        {
            [Key]
            public int Id { get; set; }
            public virtual ApplicationUser Author { get; set; }
    
            [Required(ErrorMessage = "Merci de spécifier une catégorie")]
            public string CategoryName { get; set; }
    
            [Required(ErrorMessage = "Merci de spécifier un titre")]
            [Display(Name="Title", Prompt="Titre")]
            public string Title { get; set; }
    
            [Required(ErrorMessage = "Merci de spécifier une description")]
            [Display(Name="Description", Prompt="Description")]
            public string Description { get; set; }
    
            [Required(ErrorMessage = "Merci de saisir un article")]
            [Display(Name="Content", Prompt="Saisissez votre article")]
            public string Content { get; set; }
    
            public enum ArticleStatus
            {
                Pending,
                Rejected,
                Validated
            }
    
            public ArticleStatus Status { get; set; }
        }
    }

    Category.cs

    using System.ComponentModel.DataAnnotations;
    
    namespace DevAstuces.Models
    {
        public class Category
        {
            [Key]
            public int Id { get; set; }
            public byte[] Image { get; set; }
            
            [Required]
            public string Name { get; set; }
        }
    }

    A Category is linked to an Article via this form :

    <form id="editor_pane" method="POST">
        <input list="Category" asp-for="@Model.Article.CategoryName">
        <datalist id="Category">
        @foreach(var category in Model.CategoryList)
        {
            <option value="@category.Name"></option>
        }
        </datalist>
    
        // Code omitted for clarity
    
        <div id="editor_controls">
            <button type="button" onclick="previewArticle()">Prévisualiser</button>
            <input value="Valider" type="submit">
        </div>
    </form>

    Tuesday, February 23, 2021 2:34 PM

Answers

All replies

  • User475983607 posted

    Learn LINQ fundamentals.

    https://docs.microsoft.com/en-us/ef/core/querying/

    var val = await _articleContext.Article.Where(m => m.CategoryName  == "TheValueYouAreLookingFor").ToListAsync();

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, February 23, 2021 3:59 PM
  • Tuesday, February 23, 2021 4:01 PM
  • User-1370514677 posted

    Hi @mgebhard,

    Thank you for your answer.

    I changed my code accordingly in my ArticleController.cs :

    [HttpGet]
    public async Task<IActionResult> GetArticleCategoryImage(int Id)
    {
        // Get current article through Id passed as an argument
        var current_article = await _articleContext.Article.FindAsync(Id);
        // Find which Category is linked to the current_article by retrieving the Category's Id through the current_article.CategoryName matching with Category.Name
        var category = await _articleContext.Category.SingleAsync(m => m.Name == current_article.CategoryName);
        // Get Category Image
        var ImageFile = category.Image;
    
        return File(ImageFile,"image/svg+xml");
    }

    Yet, I don't get the SVG image that is wanted in my CSHTML code (just a blank square with nothing) :

    @foreach(var article in Model.ArticleList)
    {
    <a asp-controller="Article" asp-action="GetArticle" asp-route-id="@article.Id">
        <div class="article article_a">
            <object data="/Article/GetArticleCategoryImage/@article.Id" type="image/svg+xml" class="article_category"></object>
            <div class="article_content">
                <p class="article_header">@article.Title</p>
                <div class="article_description">
                    @article.Description
                </div>
            </div>
        </div>
    </a>
    }

    Tuesday, February 23, 2021 5:01 PM
  • User475983607 posted

    There are too many potential problems with your code.  Learn how to troubleshoot code and use debugging tools.

    https://docs.microsoft.com/en-us/visualstudio/debugger/debugger-feature-tour?view=vs-2019

    I would do paste a valid controller/action URL in the browser's address bar to see if an SVG image is returned.  If you see the expected image then there is a problem elsewhere in the code.   If you do not see the expected image, open the browser's dev tools and look for errors in the network view.   Read the error go form there.

    Also set a break point in the action and view each of the variables to make sure they contain expected values.

    Tuesday, February 23, 2021 7:48 PM
  • User-1370514677 posted

    Hi @mgebhard,

    I debugged my code with your advices (I've directly copy/paste the URL in the browser) and found that the var category is actually null :

    [HttpGet]
    public async Task<IActionResult> GetArticleCategoryImage(int Id)
    {
        // Get current article through Id passed as an argument
        var current_article = await _articleContext.Article.FindAsync(Id);
    
        // Find which Category is linked to the current_article by retrieving the Category's Id through the current_article.CategoryName matching with Category.Name
        var category = await _articleContext.Category.SingleOrDefaultAsync(m => m.Name == current_article.CategoryName);
        
        if(category == null)
            System.Console.WriteLine("Category is NULL");
        
        // Get Category Image
        var ImageFile = category.Image;
    
        return File(ImageFile,"image/svg+xml");
    }

    So it seems that my LINQ query is not finding the requested category with the CategoryName I passed it.

    For example :

    • User creates an Article about csharp and select "csharp" as a Category object (present in the DB)
    • The Article.CategoryName = "csharp"
    • But the LINQ query above won't find the "csharp" Cateogry object through the string "csharp"
    Wednesday, February 24, 2021 8:47 AM
  • User475983607 posted

    But the LINQ query above won't find the "csharp" Cateogry object through the string "csharp"

    Continue troubleshooting and debugging.   The next step is solving why the LINQ query returns a null category. 

    Open the Category table and verify the table contains "csharp" in the Name column.   Use the SQL Server Object Explorer in Visual Studio or SSMS to view the table contents.

    IMHO, the design has bugs.  The Article should contain the category Id not the CategoryName.   See the following reference documentation which explains how to create a one to many relationship using Code First in EF Core.

    https://docs.microsoft.com/en-us/ef/core/

    Wednesday, February 24, 2021 12:42 PM
  • User-1370514677 posted

    EDIT : it's actually working but I forgot to recreate the categories as I deleted the DB and my browser had the former names in cache..

    Thank you anyways guys ;)

    Wednesday, February 24, 2021 2:59 PM