简体   繁体   English

如何使用外键在MVC中遍历多个类/表?

[英]How can I move through multiple classes/tables in MVC using foreign keys?

In other words, how can I traverse the "Hierarchical tree" of my classes through foreign keys? 换句话说,如何通过外键遍历类的“层次树”?

Below is a picture of the tree and associations. 下面是树和关联的图片。

这是树和关联的简要图片。

I want to loop through the tables in my view respectively. 我想分别遍历视图中的表。 It's easy to display the Survey data and Category data because I can just reference the PK and FK SurveyID from the query string. 显示调查数据和类别数据很容易,因为我只能从查询字符串中引用PK和FK SurveyID。 I'm not sure how to get the association from CategoryID to SurveyID though past that point. 我不确定在那之后如何从CategoryID到SurveyID获得关联。

Here is my View 这是我的看法

@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>
}

I tried using for (int j = 0; j < Model.Questions.Count(); j++) 我尝试使用for(int j = 0; j <Model.Questions.Count(); j ++)

but it came up with nothing and I have a feeling that it wouldn't work regardless. 但是它没有任何结果,我有一种感觉,不管如何,它是行不通的。

My guess is the problem lies not within the view, but within the controller on how it grabs the data. 我的猜测是问题不在于视图内,而在于控制器如何捕获数据。

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);
    }

Here I'm not sure if I'm supposed to use the include method or what, but I can't think of how to bridge the association between the Category and Survey ID's and then from there go on to use QuestionID. 在这里,我不确定是否应该使用include方法或什么方法,但是我无法考虑如何桥接Category和Survey ID之间的关联,然后再继续使用QuestionID。

Am I relatively close? 我比较近吗?

This looks like it may be a data access problem rather than an MVC problem. 看起来这可能是数据访问问题,而不是MVC问题。 If you're using Entity Framework, Entity Framework Loading Related Entities for how to ensure your objects are loaded. 如果您使用的是实体框架,请参阅“实体框架加载相关实体 ”以确保如何加载对象。

Also, don't load Questions into the viewModel separately as you need to preserve hierarchy. 另外,请不要将问题单独加载到viewModel中,因为需要保留层次结构。 Your TextBoxFor call for the questions should utilize that. 您对问题的TextBoxFor调用应利用该功能。

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

JamieSee pointed out that in order to get the data to show up, first eager loading must be used as shown here msdn.microsoft.com/en-us/library/jj574232(v=vs.113).aspx JamieSee指出,为了显示数据,必须使用急切加载,如下所示:msdn.microsoft.com/zh-cn/library/jj574232(v=vs.113).aspx

from there I then used a nested foreach loop. 然后从那里开始使用嵌套的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>
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;

If you want to use this query inside the VIEW, you can use with out return result; 如果要在VIEW中使用此查询,则可以使用不带返回结果的查询; Also you dont need to define any data transfer class. 另外,您不需要定义任何数据传输类。

But if you want to use inside the controller and return from any action or json result; 但是,如果您想在控制器内部使用并从任何操作或json结果返回; you must use class object for data transfer in every level of select. 您必须在每个选择级别中使用类对象进行数据传输。

For example first level DTO class can be like this; 例如,第一级DTO类可以是这样;

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

And second level DTO is; 第二级DTO是;

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

Same way the third level; 第三级相同;

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

Dont forget to add DTO names after select! 选择后不要忘记添加DTO名称! In the contreller; 在控制者中; The query changes like this; 查询更改如下:

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;

I hope the explanation clear and helps. 我希望解释清楚并有所帮助。

IF YOU USE ONE QUERY TO GET DATA IT WILL BE MORE FAST 如果您使用一个查询来获取数据,它将更加快捷

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用 LINQ 表达式 ASP.NET MVC Entity Framework 使用外键更新多个表 - How to Update multiple tables with foreign keys using LINQ expression ASP.NET MVC Entity Framework 如何使用外键在LINQ中插入两个以上的表 - How can I insert more than 2 tables in LINQ using foreign keys 如何使用外键链接3个表? - How do I link 3 tables using foreign keys? 如何通过 OnModelCreating 方法动态创建外键 - How can I through the OnModelCreating method create foreign keys dynamically MVC实体框架-来自一个字段中多个表的外键 - MVC Entity Framework - Foreign Keys from multiple tables in one field 多个表的多个外键 - Multiple foreign keys to many tables NHibernate-如何将具有多个外键的表映射到其对应的类? - NHibernate - How to map a table with multiple foreign keys to its corresponding classes? 实体框架和MVC-使用外键插入多个表 - Entity Framework & MVC - Insert into multiple table using foreign keys 如何使用来自不同表的多个外键为表提供数据 - How feed a table with multiple foreign keys from different tables 如何在Entity Framework中创建由外键组成的复合主键? - How can I create a composite primary key consisting of foreign keys to two tables in Entity Framework?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM