如何使用外键在MVC中移动多个类/表?

时间:2017-01-17 17:27:20

标签: c# asp.net-mvc foreign-keys

换句话说,我如何遍历"层次结构树"通过外键我的课程?

下面是树和关联的图片。

Here is a quick picture of the tree and associations.

我想分别遍历视图中的表格。显示调查数据和类别数据很容易,因为我可以从查询字符串中引用PK和FK SurveyID。我不知道如何通过这一点获得从CategoryID到SurveyID的关联。

这是我的观点

@using (Html.BeginForm("Save", "Surveys"))
{

<div class="form-group">
    @Html.LabelFor(m => m.SurveyId)
    @Html.TextBoxFor(m => m.Description, new { @class = "form-control" })
    @Html.ValidationMessageFor(m => m.Description)
</div>
<div class="form-group">
            @for (int i = 0; i < Model.Categories.Count; i++)
            {
                <ul>@Html.TextBoxFor(m => m.Categories[i].Description, new { @class = "form-control" })</ul>
                @Html.HiddenFor(m => m.Categories[i].CategoryId)
                @*Here is where I attempted to loop the questions based on category*@
                @*@for (int j = 0; j < Model.Categories[i].Questions.Count(); j++)*@
                {
                    @Html.TextBoxFor(m => m.Questions[j].QuestionText)
                }
            }
</div>

    @Html.HiddenFor(m => m.User.Id)
    @Html.HiddenFor(m => m.SurveyId)
    @Html.AntiForgeryToken()
    <button type="submit" class="btn btn-primary">Save</button>
}

我尝试使用for(int j = 0; j&lt; Model.Questions.Count(); j ++)

但它没有任何结果,我觉得无论如何都无法发挥作用。

我的猜测是问题不在视图内,而是在控制器内如何抓取数据。

public ActionResult Edit(int id)
    {
        var survey = _context.Surveys.SingleOrDefault(c => c.SurveyId == id);
        var categories = new List<Category>();
        categories = _context.Categories.Where(c => c.SurveyId == id).ToList();
        var questions = new List<Question>();
        //questions = _context.Questions.Include()

        //var questions = new List<Question>();
        //questions = _context.Categories.Include(c => c.SurveyId == id).ToList();
        if (survey == null)
            return HttpNotFound();

        var viewModel = new NewSurveyViewModel(survey)
        {
            Questions = questions,
            Categories = categories
        };
        return View("SurveyForm", viewModel);
    }

我不确定我是否应该使用include方法或者什么,但我不能想到如何弥合类别和调查ID之间的关联。然后从那里继续使用QuestionID。

我相对接近吗?

3 个答案:

答案 0 :(得分:0)

这看起来可能是数据访问问题而不是MVC问题。如果您正在使用实体框架,Entity Framework Loading Related Entities了解如何确保加载对象。

此外,不要将问题单独加载到viewModel中,因为您需要保留层次结构。你的TextBoxFor问题的调用应该利用它。

尝试@Html.TextBoxFor(m => m.Categories[i].Questions[j].QuestionText)

答案 1 :(得分:0)

JamieSee指出,为了显示数据,必须使用第一次急切加载,如下所示msdn.microsoft.com/en-us/library/jj574232(v=vs.113).aspx

然后我使用了嵌套的foreach循环。

<div class="form-group">
    @foreach (var category in Model.Categories.Where(q => q.SurveyId == Model.SurveyId))
    {
        <ul>@Html.TextBoxFor(m => category.Description, new { @class = "form-control" })</ul>
            @Html.HiddenFor(m => category.CategoryId)

        foreach (var question in Model.Questions.Where(q => q.CategoryId == category.CategoryId))
        {
            <ul>@Html.TextBoxFor(m => question.QuestionText, new { @class = "form-control" })</ul>
                @Html.HiddenFor(m => question.QuestionId)

            foreach (var answer in Model.Answers.Where(a => a.QuestionId == question.QuestionId))
            {
                <ul>@Html.TextBoxFor(m => answer.AnswerText, new { @class = "form-control" })</ul>
                    @Html.HiddenFor(m => answer.AnswerId)
            }
        }
    }
</div>

答案 2 :(得分:0)

var db = new DBContext() // => this is your database context

var result = from s in db.Surveys
             select new {
               survey = s,
               categories = from c in db.Categories
                            where c.SurveyID = s.ID
                            select new {
                               category = c,
                               questions = from q in db.Questions
                                           where q.CategoryID = c.ID
                                           select new {
                                               question = q,
                                               answers = from a in db.Answers
                                                         where a.QuestionID = q.ID
                                                         select a
                                            } // close the questions
                            } // close the categories
            };// close the surveys

return result;

如果要在VIEW中使用此查询,可以使用out out return result; 您也不需要定义任何数据传输类。

但是如果你想在控制器内使用并从任何动作或json结果返回;您必须在每个选择级别使用类对象进行数据传输。

例如,第一级DTO类可以是这样的;

public class SurveyDTO
{
    public Survey survey{get;set;}
    public List<CategoriesDTO> categories {get;set;}
}

第二级DTO是;

public class CategoriesDTO
{
    public Category category {get;set;}
    public List<QuestionsDTO> questions {get;set;}
}

第三级相同;

public class QuestionsDTO
{
    public Question question {get;set;}
    public List<Answer> answers{get;set;}
}

选择后别忘了添加DTO名称!在contreller;查询会像这样改变;

var db = new DBContext() // => this is your database context

var result = (from s in db.Surveys
             select new SurveyDTO(){
               survey = s,
               categories = (from c in db.Categories
                            where c.SurveyID = s.ID
                            select new CategoriesDTO(){
                               category = c,
                               questions = (from q in db.Questions
                                           where q.CategoryID = c.ID
                                           select new QuestionsDTO(){
                                               question = q,
                                               answers = (from a in db.Answers
                                                         where a.QuestionID = q.ID
                                                         select a).ToList()
                                            }).ToList() // close the questions
                            }).ToList() // close the categories
            }).ToList();// close the surveys

return result;

我希望解释明确并有所帮助。

如果您使用一个查询来获取数据,那将会更加快速