Search code examples
c#asp.net-mvclambdaentity-framework-6asp.net-identity-2

When I try navigating to third level entity properties, I can't find Select method with lambda expression inside Include method


I have a problem about accessing third level navigation properties in my context. I have searched a lot for two days but could not find any issue close to mine. So I thought that I have a logical mistake about my approach.

I use the MVC template project. Model classes and context are below.

public partial class Tests
{

    [Key]
    public int TestID { get; set; }
    public string TestName { get; set; }
    public List<UserTests> UserTests { get; set; }
}

public partial class UserTests
{
    [Key, Column(Order=1)]
    public string UserID { get; set; }
    [Key, Column(Order = 2)]
    public int TestID { get; set; }
    public Nullable<double> TestValue { get; set; }
    public ApplicationUser ApplicationUser { get; set; }
    public Tests Tests { get; set; }
}

public partial class UserDetail
{

    [Key]
    public int ID { get; set; }
    public string UserID { get; set; }
    public string Name { get; set; }
    public ApplicationUser ApplicationUser { get; set; }
}

public class ApplicationUser : IdentityUser
{
    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        // Add custom user claims here
        return userIdentity;
    }

    public List<UserTests> UserTests { get; set; }
    public List<UserDetail> UserDetails { get; set; }

}

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("DefaultConnection", throwIfV1Schema: false)
    {
        this.Configuration.ProxyCreationEnabled = false;
        this.Configuration.LazyLoadingEnabled = false;
    }

    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }

    public IDbSet<Tests> Tests { get; set; }
    public IDbSet<UserDetail> UserDetails { get; set; }
    public IDbSet<UserTests> UserTests { get; set; }


}

I try to reach UserDetails properties from UserTests. But I can't find Select method inside the Include method clicking dot after ApplicationUser.

public ActionResult Index()
    {
        var userTests = db.UserTests.Include(u => u.Tests).Include(y => y.ApplicationUser.UserDetails);
        return View(userTest.ToList());
    }

This is the index view.

    @model IEnumerable<WebApplication6.Models.UserTests>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.ApplicationUser.Email)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Tests.TestName)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.TestValue)
        </th>

    </tr>

@foreach (var item in Model) {
    <tr>
        <th>
            @Html.DisplayFor(modelItem => item.ApplicationUser.Email)
        </th>
        <td>
            @Html.DisplayFor(modelItem => item.Tests.TestName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.TestValue)
        </td>

        <td>
            @Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
            @Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
            @Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
        </td>
    </tr>
}

</table>

I want the view to display ApplicationUser's Name instead of Email which is in the UserDetails model class. So I want to type a Razor code like below but I can't. There is no Name property after UserDetails

@Html.DisplayNameFor(model => model.ApplicationUser.UserDetails.Name)
  1. Why can't I find Select method there?
  2. Is there any way to access UserDetails properties from UserTests with include or another ef method?
  3. If not, how to send a model to the view that can be accessible to UserTests, ApplicationUser and UserDetails properties?
  4. How can I achieve to display UserDetails.Name property instead of ApplicationUser.Email property?

Solution

  • This is the Include you're looking for:

    db.UserTests.Include(x => x.ApplicationUser.UserDetails);