locked
Is it possible to have multiple navigation classes ? RRS feed

  • Question

  • User-973886032 posted

    hi guys

    I have a class with PK and FK relationships.

    Is it possible to have multiple navigation properties e.g. 

    MY QUESTION

    I am trying to get 2 values from the class Departments_Category which are values from the class, based on a PK and FK 

    at the same time, I want to get the count from the list from the same Departments_Category 

    Is this possible and how ?

    many thanks

    Ehi

         public class Departments 
        {
    
           [Key]
           // This is the PK
            public int DepartmentID { get; set; } // this is a FK
    
            [ForeignKey("DepartmentID")]
            public SubDepartments SubDepartments { get; set; }
    
           [ForeignKey("DepartmentID")]
            public Departments_Category Departments_Category { get; set; }
    
            public List<Departments_Category> Departments_Category { get; set; }
            public int Count {get; set;}
    
            public string Category_Name { get; set; }
            public DateTime EntryDate { get; set; }
            public string Description { get; set; }
            public string Description_Detail { get; set; }
            public string Notes { get; set; }
            public string Reference { get; set; }
            public Guid UniqueId { get; set; }
            public bool IsEnabled { get; set; }

    Tuesday, July 16, 2019 9:32 PM

Answers

  • User711641945 posted

    Hi afrika,

    I change the List<int> to List<Departments_Category>.And here is my working demo:

    1.Model:

    public class Departments
        {
            [Key]
            // This is the PK
            public int DepartmentID { get; set; }      
            public List<Departments_Category> Departments_Categories { get; set; }
            public int Count { get; set; }
            public bool IsEnabled { get; set; }
        }
    public class Departments_Category
        {
            [Key]
            public int CategoryID { get; set; }              // This is the PK
            public int DepartmentID { get; set; } // this is a FK
            public string Category_Name { get; set; }
            public Departments Departments { get; set; }
        }
    public class DepartmentViewModel
        {
            public int DepartmentID { get; set; }
            public List<Departments_Category> Departments_Category { get; set; }
            public int Count { get; set; }
        }

    2.View:

    @model IEnumerable<DepartmentViewModel>
    <h1>Index</h1>
    <p>
        <a asp-action="Create">Create New</a>
    </p>
    <table class="table">
        <thead>
            <tr>
                <th>
                    @Html.DisplayNameFor(model => model.DepartmentID)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Departments_Category)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Count)
                </th>
                <th></th>
            </tr>
        </thead>
        <tbody>
            @foreach (var item in Model)
            {
                <tr>
                    <td>
                        @Html.DisplayFor(modelItem => item.DepartmentID)
                    </td>
                    <td>
                        @foreach (var iditem in item.Departments_Category)
                        {
                            <label>CategoryId:</label>
                            @Html.DisplayFor(modelItem=>iditem.CategoryID)<br/>
                            <label>CategoryName:</label>
                            @Html.DisplayFor(modelItem=>iditem.Category_Name)
                            <hr/>
                        }
    
                    </td>
                    <td>
                        @Html.DisplayFor(modelItem => item.Count)
                    </td>
                </tr>
            }
        </tbody>
    </table>

    3.Controller:

    public async Task<IActionResult> Category(int id)
            {
                var category = await _context.Departments.Include(d => d.Departments_Categories)
                    .Where(d => d.DepartmentID == id)
                    .Select(u => new DepartmentViewModel
                    {
                        DepartmentID = u.DepartmentID,
                        Departments_Category = u.Departments_Categories.ToList(),
                        Count = u.Departments_Categories.Count()
                    }).ToListAsync();
                return View(category);
            }

    4.Result:

    Best Regards,

    Rena

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, July 30, 2019 8:12 AM

All replies

  • User711641945 posted

    Hi afrika,

    Is it possible to have multiple navigation properties e.g. 

    No. EF Core will be unable to determine the relationship represented by navigation property 'Departments.Departments_Category' of type 'Departments_Category’.

    You could use a ViewModel to show what you want, here is a working demo:

    1.Departments.cs :

    public class Departments
        {
            [Key]
            // This is the PK
            public int DepartmentID { get; set; } 
             //[ForeignKey("DepartmentID")]
            //public Departments_Category Departments_Category { get; set; }
            public List<Departments_Category> Departments_Categories { get; set; }
            public int Count { get; set; }
            public bool IsEnabled { get; set; }
            //more property…
        }
    

    2.Departments_Category.cs :

    public class Departments_Category
        {
            [Key]
            public int CategoryID { get; set; }    // This is the PK
            public string Category_Name { get; set; }
            public int DepartmentID { get; set; }// This is the FK
            public Departments Departments { get; set; }
        }
    

    3.DepartmentViewModel.cs :

    public class DepartmentViewModel
        {
            public int DepartmentID { get; set; }
            public List<int> CategoryID { get; set; }
            public int Count { get; set; }
        }
    

    4.Action :

    public async Task<IActionResult> Category(int id)
            {
                var category = await _context.Departments.Include(d => d.Departments_Categories)
                    .Where(d => d.DepartmentID == id)
                    .Select(u => new DepartmentViewModel
                    {
                        DepartmentID = u.DepartmentID,
                        CategoryID=u.Departments_Categories.Select(c=>c.CategoryID).ToList(),
                        Count = u.Departments_Categories.Count()
                    }).ToListAsync();
                return View(category);
            }
    

    I think you may be a bit fuzzy about EF core. You could refer to this link to learn how to define relationship:

    https://docs.microsoft.com/en-us/ef/core/modeling/relationships#fully-defined-relationships

    Best Regards,

    Rena

     

    Wednesday, July 17, 2019 5:28 AM
  • User-973886032 posted

    thanks for your reply and code

    I get the error below. however I was wondering about your code, especially the line highlighted in yellow below

    can an in be a list ???

          public List<int> CategoryID { get; set; }
    ArgumentException: Expression of type 'System.Int32' cannot be used for parameter of type 'System.Object' of method 'Int32 Property[Int32](System.Object, System.String)' Parameter name: arg0

    Wednesday, July 17, 2019 11:50 AM
  • User711641945 posted

    Hi afrika,

    can an in be a list ???

          public List<int> CategoryID { get; set; }

    You said you want to get the value of DepartmentId and CategoryId. The relationship between Department class and Category class is one-to-many. So CategoryId could be a list.

    ArgumentException: Expression of type 'System.Int32' cannot be used for parameter of type 'System.Object' of method 'Int32 Property[Int32](System.Object, System.String)' Parameter name: arg0

    Did you use my code and get the error? If not, could you share a simple demo with the model and action that could reproduce your issue?

    Best Regards,

    Rena

    Thursday, July 18, 2019 1:32 AM
  • User-973886032 posted

    hi Rena

    thanks for your help. Sorry I have been out of town and back now, hence late reply

    I finally got this to work, I changed the int datatype to the actual object and it worked. as the error kept complaining about it being an int instead of an object

    Here is the code modification in the viewmodel

    3.DepartmentViewModel.cs :

    public class DepartmentViewModel
        {
            public int DepartmentID { get; set; }
            public List<int> CategoryID { get; set; } // I changed this 
            public int Count { get; set; }
        }

    I changed the above highlighted in yellow the below highlighted in green

       public List<Departments_Category> Departments_Category { get; set; }

    If you kindly update your code, I can then mark it as an answer, so it would be helpful to others. Many thanks

    Monday, July 29, 2019 8:46 AM
  • User753101303 posted

    Hi,

    First I suspect there is some kind of confusion between the entity model (ie shaped objects tailored for data persistance) and your view model (ie shaped objects tailored for what you want to show in a view). It feels like you have for now a single class definition you try to design based on both what you want to have in your db and what you want to show in your view?

    If confirmed you should first design your Entity Model regardless of what you want to show on your view. the. The Departments entity class you posted first seems contradictory :
    - it have a single Departements_Category as well as a list of Departements_Category and also a Category_Name property? This is what make me think you try to design your EF entity based also on what you finally want to show in your view rather than only on how data should be persisted to your db.

    Then it seems that later you'll want to show in your view a Departement as well as the count of how many departements are found in the same Category ? (or maybe you want the list of all departements in a category with a currently selected departement ???)

    Edit: or if DepartmentViewModel is ok, the problem for now is that you are using apparently one of the entry in the CategoryID list as an object rather than as an integer.  The error message should show on which line it happens so that you could fix this (but for now I'm not sure this is what you really want).

    Monday, July 29, 2019 4:22 PM
  • User711641945 posted

    Hi afrika,

    I change the List<int> to List<Departments_Category>.And here is my working demo:

    1.Model:

    public class Departments
        {
            [Key]
            // This is the PK
            public int DepartmentID { get; set; }      
            public List<Departments_Category> Departments_Categories { get; set; }
            public int Count { get; set; }
            public bool IsEnabled { get; set; }
        }
    public class Departments_Category
        {
            [Key]
            public int CategoryID { get; set; }              // This is the PK
            public int DepartmentID { get; set; } // this is a FK
            public string Category_Name { get; set; }
            public Departments Departments { get; set; }
        }
    public class DepartmentViewModel
        {
            public int DepartmentID { get; set; }
            public List<Departments_Category> Departments_Category { get; set; }
            public int Count { get; set; }
        }

    2.View:

    @model IEnumerable<DepartmentViewModel>
    <h1>Index</h1>
    <p>
        <a asp-action="Create">Create New</a>
    </p>
    <table class="table">
        <thead>
            <tr>
                <th>
                    @Html.DisplayNameFor(model => model.DepartmentID)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Departments_Category)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Count)
                </th>
                <th></th>
            </tr>
        </thead>
        <tbody>
            @foreach (var item in Model)
            {
                <tr>
                    <td>
                        @Html.DisplayFor(modelItem => item.DepartmentID)
                    </td>
                    <td>
                        @foreach (var iditem in item.Departments_Category)
                        {
                            <label>CategoryId:</label>
                            @Html.DisplayFor(modelItem=>iditem.CategoryID)<br/>
                            <label>CategoryName:</label>
                            @Html.DisplayFor(modelItem=>iditem.Category_Name)
                            <hr/>
                        }
    
                    </td>
                    <td>
                        @Html.DisplayFor(modelItem => item.Count)
                    </td>
                </tr>
            }
        </tbody>
    </table>

    3.Controller:

    public async Task<IActionResult> Category(int id)
            {
                var category = await _context.Departments.Include(d => d.Departments_Categories)
                    .Where(d => d.DepartmentID == id)
                    .Select(u => new DepartmentViewModel
                    {
                        DepartmentID = u.DepartmentID,
                        Departments_Category = u.Departments_Categories.ToList(),
                        Count = u.Departments_Categories.Count()
                    }).ToListAsync();
                return View(category);
            }

    4.Result:

    Best Regards,

    Rena

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, July 30, 2019 8:12 AM
  • User-973886032 posted

    Hi afrika,

    I change the List<int> to List<Departments_Category>.And here is my working demo:

    1.Model:

    public class Departments
        {
            [Key]
            // This is the PK
            public int DepartmentID { get; set; }      
            public List<Departments_Category> Departments_Categories { get; set; }
            public int Count { get; set; }
            public bool IsEnabled { get; set; }
        }
    public class Departments_Category
        {
            [Key]
            public int CategoryID { get; set; }              // This is the PK
            public int DepartmentID { get; set; } // this is a FK
            public string Category_Name { get; set; }
            public Departments Departments { get; set; }
        }
    public class DepartmentViewModel
        {
            public int DepartmentID { get; set; }
            public List<Departments_Category> Departments_Category { get; set; }
            public int Count { get; set; }
        }

    2.View:

    @model IEnumerable<DepartmentViewModel>
    <h1>Index</h1>
    <p>
        <a asp-action="Create">Create New</a>
    </p>
    <table class="table">
        <thead>
            <tr>
                <th>
                    @Html.DisplayNameFor(model => model.DepartmentID)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Departments_Category)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Count)
                </th>
                <th></th>
            </tr>
        </thead>
        <tbody>
            @foreach (var item in Model)
            {
                <tr>
                    <td>
                        @Html.DisplayFor(modelItem => item.DepartmentID)
                    </td>
                    <td>
                        @foreach (var iditem in item.Departments_Category)
                        {
                            <label>CategoryId:</label>
                            @Html.DisplayFor(modelItem=>iditem.CategoryID)<br/>
                            <label>CategoryName:</label>
                            @Html.DisplayFor(modelItem=>iditem.Category_Name)
                            <hr/>
                        }
    
                    </td>
                    <td>
                        @Html.DisplayFor(modelItem => item.Count)
                    </td>
                </tr>
            }
        </tbody>
    </table>

    3.Controller:

    public async Task<IActionResult> Category(int id)
            {
                var category = await _context.Departments.Include(d => d.Departments_Categories)
                    .Where(d => d.DepartmentID == id)
                    .Select(u => new DepartmentViewModel
                    {
                        DepartmentID = u.DepartmentID,
                        Departments_Category = u.Departments_Categories.ToList(),
                        Count = u.Departments_Categories.Count()
                    }).ToListAsync();
                return View(category);
            }

    4.Result:

    Best Regards,

    Rena

    many thanks

    Tuesday, July 30, 2019 2:46 PM