简体   繁体   中英

How to populate a view models using a linq query ASP.NET MVC 5 Entity Framework

Ok so this is a follow-up from MVC 5 ASP.NET Entity Framework Collect Form Data through Range Input , My Database Structure Consists of a Survey Having Many Categories, A Category having many Questions, then a Question having many QuestionResults and finally QuestionResults having many CategoryResults, in the HomeController I have the models being bound through the ViewModel, but I now require it to be populated with my entities through the context with Linq, any help will be greatly appreciated.

I need to populate this ViewModel, which was created with the help of a very valuable stack-overflow contributor, with my Entities, all code is as below:

Main question: How can I bring in my entities into my SurveyVM ViewModel instance?

ViewModel

namespace MyApp
{
    public class SurveyVM
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public List<CategoryVM> Categories { get; set; }
    }

    public class CategoryVM
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public List<QuestionVM> Questions { get; set; }
    }

    public class QuestionVM
    {
        public int ID { get; set; }
        public string Title { get; set; }
        public int Score { get; set; }
    }

    public class QuestionResult
    {
        public int ID { get; set; }
        public int QuestionId { get; set; }
        public int QuestionScore { get; set; }
    }
}

Models Linked to Entities and Subsequent Database

public class Question
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public string CreatedBy { get; set; }
        public DateTime? DateCreated { get; set; }
        public DateTime? DateModified { get; set; }
        public virtual Category Category { get; set; }
        public int CategoryId { get; set; }
        public virtual ICollection<QuestionResult> QuestionResult { get; set; }
        public virtual ICollection<QuestionFeedback> QuestionFeedback { get; set; }
    }
public class QuestionResult
    {
        public int Id { get; set; }
        public DateTime? DateCreated { get; set; }
        public DateTime? DateModified { get; set; }
        public int QuestionScore { get; set; }
        //navigation properties
        public virtual ApplicationUser User { get; set; }
        public ICollection<CategoryResult> CategoryResult { get; set; }
        public virtual Question Question { get; set; }
        public int QuestionId { get; set; }
    }
public class CategoryResult
    {
        public int Id { get; set; }
        public int CategoryScore {get;set;}
        //navigation properties
        public virtual QuestionResult QuestionResult { get; set; }
        public int QuestionResultId { get; set; }

    }
public class Category
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public string CreatedBy { get; set; }
        public DateTime? DateCreated { get; set; }
        public DateTime? DateModified { get; set; }
        public virtual Survey Survey { get; set; }
        public int SurveyId { get; set; }
        public virtual ICollection<Question> Question { get; set; }
        public virtual ICollection<CategoryFeedback> CategoryFeedback { get; set; }
    }

HomeController

public ActionResult IndexSurveyViewModel()
        {
            SurveyVM model = new SurveyVM()
            {
                ID = 1,
                Name = "Survey 1",
                Categories = new List<CategoryVM>()
                {
                    new CategoryVM()
                    {
                        ID = 1, 
                        Name = "Category A", 
                        Questions = new List<QuestionVM>()
                        {
                            new QuestionVM()
                            {
                                ID = 1, Title = "Question 1A", Score = 2
                            }, 
                                new QuestionVM()
                            {
                                ID = 2, Title = "Question 2A", Score = 4
                            }
                        }
                    },
                    new CategoryVM()
                    {
                        ID = 1, 
                        Name = "Category B", 
                        Questions = new List<QuestionVM>()
                        {
                            new QuestionVM()
                            {
                                ID = 3, Title = "Question 1B", Score = 3
                            }, 
                                new QuestionVM()
                            {
                                ID = 4, Title = "Question 2B", Score = 5
                            }
                        }
                    },
                    new CategoryVM()
                    {
                        ID = 1, 
                        Name = "Category C", 
                        Questions = new List<QuestionVM>()
                        {
                            new QuestionVM()
                            {
                                ID = 5, Title = "Question 1C", Score = 1
                            }, 
                                new QuestionVM()
                            {
                                ID = 6, Title = "Question 2C", Score = 3
                            }
                        }
                    }   
                }
            };
            return View(model);
        }

        [HttpPost]
        public ActionResult IndexSurveyViewModel(SurveyVM model)
        {
            List<QuestionResult> results = new List<QuestionResult>();
            foreach (CategoryVM category in model.Categories)
            {
                foreach (QuestionVM question in category.Questions)
                {
                    results.Add(new QuestionResult()
                    {
                        Id = question.ID,
                        QuestionScore = question.Score
                    });

                }
            }
            return View(model);
        }

View

@model STRA.Models.SurveyVM
@{
    Layout = null;
}

<!DOCTYPE html>


<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>My app</title>
    <link rel="stylesheet" href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
    <style>
        .category {
            display: none;
            margin-left: 20px;
            margin-top: 10px;
        }

            .category:first-of-type {
                display: block;
            }

                .category:first-of-type button:last-of-type {
                    display: none;
                }

            .category:last-of-type button:first-of-type {
                display: none;
            }

        .question {
            margin-left: 20px;
            margin-top: 10px;
        }

        .buttons {
            margin: 20px;
        }

        input[type="text"] {
            width: 20px;
        }

        .slider {
            display: inline-block;
            width: 200px;
            margin-left: 20px;
        }
    </style>
</head>


<body>
    @using (Html.BeginForm())
    {
        @Html.HiddenFor(m => m.ID)
        @Html.DisplayFor(m => m.Name)
        for (int i = 0; i < Model.Categories.Count; i++)
        {
            <div class="category">
                @Html.HiddenFor(m => m.Categories[i].ID)
                @Html.DisplayFor(m => m.Categories[i].Name)
                @for (int j = 0; j < Model.Categories[i].Questions.Count; j++)
                {
                    <div class="question">
                        @Html.HiddenFor(m => m.Categories[i].Questions[j].ID)
                        @Html.DisplayFor(m => m.Categories[i].Questions[j].Title)
                        @Html.TextBoxFor(m => m.Categories[i].Questions[j].Score)
                        <div class="slider"></div>
                    </div>
                }
                <div class="buttons">
                    <button type="button" class="next">Next</button>
                    <button type="button" class="previous">Previous</button>
                </div>
            </div>
        }
        <input type="submit" />
    }


    <!-- JS includes -->
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
    <script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
    <script src="//ajax.aspnetcdn.com/ajax/jquery.validate/1.11.1/jquery.validate.min.js"></script>
    <script src="//ajax.aspnetcdn.com/ajax/mvc/4.0/jquery.validate.unobtrusive.min.js"></script>

    <script type="text/javascript">

            $('.slider').each(function() {
                var v = $(this).closest('.question').find('input[type="text"]').val();
                $(this).slider({
                    value: v,
                    min: 1,
                    max: 5,
                    change: function (event, ui) {
                        $(this).closest('.question').find('input[type="text"]').val(ui.value);
                    }
                });
            });
            $('.next').click(function() {
                $(this).closest('.category').hide().next('.category').show();
            });
            $('.previous').click(function() {
                $(this).closest('.category').hide().prev('.category').show();
            });
    </script>
</body>
</html>

My Code so far:

var survey = from s in db.Surveys
                         from c in db.Categories
                         from q in db.Questions
                         where s.Id == c.SurveyId
                         where c.Id == q.CategoryId
                         select new SurveyVM
                         {
                             ID = s.Id,
                             Name = s.Title,
                             Categories = new List<CategoryVM>()
                             {
                                 new CategoryVM()
                                 {
                                     ID = c.Id,
                                     Name = c.Title,
                                     Questions = new List<QuestionVM>()
                                     {
                                         new QuestionVM()
                                         {
                                             ID = q.Id,
                                             Title = q.Title
                                         }
                                     }
                                 }
                             }
                         };

How can I bring in my entities into my SurveyVM ViewModel instance?

This might point you in the right direction, its using lambda expressions.

List<SurveyVM> surveys = DbContext.Survey.Select(s=> new SurveyVM {
    ID = s.ID,
    Name = s.Name,
    Categories = s.Category.Select(c => new CategoryVM {
        ID = c.ID,
        Name = c.Name,
        Questions = c.Question.Select(q=> new QuestionVM {
            ID = q.ID,
            Title = q.Title,
            Score = q.Score
        }).ToList()
    }).ToList()
}).SingleOrDefault();

This is off the top of my head as I dont have anything to test it with.

Also as a side note I would look at using EditorTemplates/DisplayTemplates instead of your loop in your view as it will make your code easier to read.

for (int i = 0; i < Model.Categories.Count; i++)
    {
        <div class="category">
            @Html.HiddenFor(m => m.Categories[i].ID)
            @Html.DisplayFor(m => m.Categories[i].Name)
            @for (int j = 0; j < Model.Categories[i].Questions.Count; j++)
            {
                <div class="question">
                    @Html.HiddenFor(m => m.Categories[i].Questions[j].ID)
                    @Html.DisplayFor(m => m.Categories[i].Questions[j].Title)
                    @Html.TextBoxFor(m => m.Categories[i].Questions[j].Score)
                    <div class="slider"></div>
                </div>
            }
            <div class="buttons">
                <button type="button" class="next">Next</button>
                <button type="button" class="previous">Previous</button>
            </div>
        </div>
    }

When you have Domain models and each of domain model have a lot of view models then it is the right time to use Automapper . All documentation you can find here:

https://github.com/AutoMapper/AutoMapper/wiki/Getting-started

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM