Error accessing navigation property in EF First code

I have a simple ViewModel that has something like this ...

ViewModel

public class UserPostCommentViewModel { public virtual List<Comment> Comment { get; set; } public virtual User User { get; set; } public virtual Post Post { get; set; } } 

so that I can return a view that has 1 post with details of 1 user information and a lot of comments submitted by users ....

Post

  [Key] [ScaffoldColumn(true)] public int PostID { get; set; } [Required(ErrorMessage="Required")] [StringLength(250)] public string Title { get; set; } [Required(ErrorMessage="Required")] [DataType(DataType.MultilineText)] public string Body { get; set; } [DataType(DataType.Date)] public DateTime DateCreated { get; set; } [DataType(DataType.Date)] public DateTime DateModified { get; set; } [ScaffoldColumn(false)] public int UserID { get; set; } [ScaffoldColumn(false)] public int? TagID { get; set; } public virtual ICollection<Comment> Comments { get; set; } public virtual User Users { get; set; } public virtual ICollection<Tag> Tags { get; set; } 

A comment

 [Key] [ScaffoldColumn(true)] public int CommentID { get; set; } [DisplayName("Your Comment")] [DataType(DataType.MultilineText)] public string Body { get; set; } [DataType(DataType.Date)] [ScaffoldColumn(true)] public DateTime DateCreated { get; set; } [ScaffoldColumn(true)] public int PostID { get; set; } [ScaffoldColumn(true)] public int UserID { get; set; } public User User { get; set; } public Post Posts { get; set; } 

USER

 [ScaffoldColumn(true)] [Key] public int UserID { get; set; } [StringLength(15)] [DisplayName("First Name")] [Required(ErrorMessage="First Name is Required")] public string FirstName { get; set; } [StringLength(15)] [DisplayName("Last Name")] [Required(ErrorMessage = "Last Name is Required")] public string LastName { get; set; } [DataType(DataType.EmailAddress,ErrorMessage="please enter valid email")] [DisplayName("Email Address")] [Required(ErrorMessage = "Email is Required")] [Remote("CheckUniqueEmail","User",ErrorMessage="An account with this email address already exists.")] public string Email { get; set; } [DataType(DataType.Password)] [Required(ErrorMessage = "Password is Required")] public string Password { get; set; } [DataType(DataType.Date)] [ScaffoldColumn(true)] public DateTime JoiningDate { get; set; } [DataType(DataType.Date)] [ScaffoldColumn(true)] public DateTime? LastActivityDate { get; set; } public virtual ICollection<Post> Posts { get; set; } public virtual ICollection<Comment> Comments { get; set; } public virtual ICollection<Tag> Tags { get; set; } 

I have a Strongly Typed View with a ViewModel so that I can return all three properties of the model in one view ...

BUT :( I want to show userName instead of userID before each comment for this particular post. Therefore, I use ICollection comments in the viewmodel so that I can return a collection of comments. When I try to access the userName property like this @ Model.Comments.User. LastName // OR Email // OR FirstName .. I get a compilation error and I cannot use it like that because its collection type ...

how can I get the username from the comments object using the user id available in the comments.

please, help...

Got it all by adding a partial view.

_Comments Partial View ..

in my partial view, I added like this:

==========================

 @{ ContextRepository db = new ContextRepository(); var userID = Model.UserID; var userName = db.EUser.Find(userID).FirstName; } 
0
source share
1 answer

You can create a partial view to display the comment and call it inside the loop in the main view.

Message Appearance

 @model UserPostCommentViewModel @{ ViewBag.Title = "Post"; Layout = "~/Views/Shared/_Layout.cshtml"; } @foreach (Comment comment in Model.Comments) { @Html.Partial("_Comment", comment); } 

Partial Comment Type

 @model Comment <div class="comment"> <div class="desc">@Model.Body</div> <div class="submitted-by">@Model.User.LastName</div> </div> 

Model Issues

You need to make the navigation properties virtual so that they are lazy loaded.

 public class Comment { //other properties public virtual User User { get; set; } public virtual Post Posts { get; set; } } 

If you want to access these navigation properties, you will need to download them. Otherwise, you will run into Select n+1 . Use the Include method to satisfy loaded properties.

 var post = db.Posts.Include(p => Comments) .Include(p => p.Comments.Select(c => c.User)) .Where(p => p.PostID == 1).Single(); 
0
source

Source: https://habr.com/ru/post/1335483/


All Articles