使用LINQ-To-Sql和ASP.NET MVC的多对多

时间:2022-09-18 08:49:50

I will restrict this to the three tables I am trying to work with Problem, Communications, and ProbComms. The scenario is that a Student may have many Problems concurrently which may affect their studies. Lecturers may have future communications with a student after an initial problem is logged, however as a Student may have multiple Problems the Lecturer may decide that the discussion they had is related to more than one Problem.

我将这个限制在我尝试使用Problem,Communications和ProbComms的三个表中。情景是学生可能同时有许多问题,这可能会影响他们的学习。在记录初始问题后,讲师可能会与学生进行未来的沟通,但是由于学生可能有多个问题,讲师可能会认为他们的讨论与多个问题有关。

Here is a screenshot of the LINQ-To-Sql representation of my DB:

以下是我的数据库的LINQ-To-Sql表示的屏幕截图:

LINQ-To-Sql Screenshot

LINQ-To-Sql截图

At the moment in my StudentController I have a StudentFormViewModel Class:

在我的StudentController中,我有一个StudentFormViewModel类:

    //
//ViewModel Class
public class StudentFormViewModel
{
    IProbCommRepository probCommRepository;

    // Properties
    public Student Student { get; private set; }
    public IEnumerable<ProbComm> ProbComm { get; private set; }

    //
    // Dependency Injection enabled constructors
    public StudentFormViewModel(Student student, IEnumerable<ProbComm> probComm)
        : this(new ProbCommRepository())
    {
        this.Student = student;
        this.ProbComm = probComm;
    }

    public StudentFormViewModel(IProbCommRepository pRepository)
    {
        probCommRepository = pRepository;
    }
}

When I go to the Students Detail Page this runs:

当我进入学生详细信息页面时,这会运行:

        public ActionResult Details(string id)
    {
        StudentFormViewModel viewdata = new StudentFormViewModel(studentRepository.GetStudent(id),
            probCommRepository.FindAllProblemComms(id));

        if (viewdata == null)
            return View("NotFound");
        else
            return View(viewdata);
    }

The GetStudent works fine and returns an instance of the student to output on the page, below the student I output all problems logged against them, but underneath these problems I want to show the communications related to the Problem.

GetStudent工作正常并返回学生的实例以在页面上输出,在学生下面我输出针对他们记录的所有问题,但在这些问题下面我想显示与问题相关的通信。

The LINQ I am using for ProbComms is This is located in the Model class ProbCommRepository, and accessed via a IProbCommRepository interface:

我用于ProbComms的LINQ是位于Model类的ProbCommRepository中,可通过IProbCommRepository接口访问:

        public IQueryable<ProbComm> FindAllProblemComms(string studentEmail)
    {
        return (from p in db.ProbComms
                where p.Problem.StudentEmail.Equals(studentEmail)
                orderby p.Problem.ProblemDateTime
                select p);
    }

However for example if I have this data in the ProbComms table:

但是,例如,如果我在ProbComms表中有这些数据:

ProblemID CommunicationID 1 1 1 2

ProblemID CommunicationID 1 1 1 2

The query returns two rows so I assume I somehow have to groupby Problem or ProblemID but I am not too sure how to do this with the way I have built things as the return type has to be ProbComm for the query as thats what Model class its located in.

查询返回两行所以我假设我不知何故必须groupby问题或ProblemID但我不太清楚如何用我构建的东西做这个,因为返回类型必须是ProbComm的查询,因为那是什么Model类的位于。

When it comes to the view the Details.aspx calls two partial views each passing the relevant view data through, StudentDetails works fine page:

当谈到视图时,Details.aspx调用两个部分视图,每个部分视图都传递相关的视图数据,StudentDetails工作正常:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"  Inherits="System.Web.Mvc.ViewPage<MitigatingCircumstances.Controllers.StudentFormViewModel>" %>
<% Html.RenderPartial("StudentDetails", this.ViewData.Model.Student); %>
<% Html.RenderPartial("StudentProblems", this.ViewData.Model.ProbComm); %>

StudentProblems uses a foreach loop to loop through records in the Model and I am trying another foreach loop to output the communication details:

StudentProblems使用foreach循环遍历模型中的记录,我正在尝试另一个foreach循环来输出通信详细信息:

    <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<MitigatingCircumstances.Models.ProbComm>>" %>

<script type="text/javascript" language="javascript">
    $(document).ready(function() {
        $("DIV.ContainerPanel > DIV.collapsePanelHeader > DIV.ArrowExpand").toggle(
                function() {
                    $(this).parent().next("div.Content").show("slow");
                    $(this).attr("class", "ArrowClose");
                },
                function() {
                    $(this).parent().next("div.Content").hide("slow");
                    $(this).attr("class", "ArrowExpand");
                });

    });           
</script>
    <div class="studentProblems">    
    <% var i = 0;

       foreach (var item in Model) { %>
            <div id="ContainerPanel<%= i = i + 1 %>" class="ContainerPanel">
                <div id="header<%= i = i + 1 %>" class="collapsePanelHeader">
                    <div id="dvHeaderText<%= i = i + 1 %>" class="HeaderContent"><%= Html.Encode(String.Format("{0:dd/MM/yyyy}", item.Problem.ProblemDateTime))%></div>
                    <div id="dvArrow<%= i = i + 1 %>" class="ArrowExpand"></div>
                </div>
                <div id="dvContent<%= i = i + 1 %>" class="Content" style="display: none">
                    <p>
                        Type: <%= Html.Encode(item.Problem.CommunicationType.TypeName) %>
                    </p>
                    <p>
                        Problem Outline:  <%= Html.Encode(item.Problem.ProblemOutline)%>
                    </p>
                    <p>
                        Mitigating Circumstance Form: <%= Html.Encode(item.Problem.MCF)%>
                    </p>
                    <p>
                        Mitigating Circumstance Level: <%= Html.Encode(item.Problem.MitigatingCircumstanceLevel.MCLevel)%>
                    </p>
                    <p>
                        Absent From: <%= Html.Encode(String.Format("{0:g}", item.Problem.AbsentFrom))%>
                    </p>
                    <p>
                        Absent Until:  <%= Html.Encode(String.Format("{0:g}", item.Problem.AbsentUntil))%>
                    </p>
                    <p>
                        Requested Follow Up:  <%= Html.Encode(String.Format("{0:g}", item.Problem.RequestedFollowUp))%>
                    </p>

                    <p>Problem Communications</p>
                    <% foreach (var comm in Model) { %>                            
                            <p>
                            <% if (item.Problem.ProblemID == comm.ProblemID)
                               { %>
                                    <%= Html.Encode(comm.ProblemCommunication.CommunicationOutline)%>
                            <% } %>
                            </p>
                 <% } %>
                   </div>
            </div>
            <br />
    <% } %>
    </div>

The issue is that using the example data before the Model has two records for the same problem as there are two communications for that problem, therefore duplicating the output.

问题是在模型之前使用示例数据有两个记录用于同一问题,因为该问题有两个通信,因此重复输出。

Any help with this would be gratefully appreciated.

如有任何帮助,将不胜感激。

Thanks,

谢谢,

Jon

乔恩

1 个解决方案

#1


1  

I have recently struggled greatly with many to many relationships in MVC. I've finally gotten mine working. I'd love to help you out, but do not fully understand your problem.

我最近在MVC中与很多关系斗争得很厉害。我终于让我的工作了。我很乐意帮助你,但不能完全理解你的问题。

When you say that the query returns 2 rows, I would think that it should since there are 2 communications for that problem. If you want to return problems for a student, you do not need to query the ProbComms table, just the Problem table. Then if you want to return communications for those problems, query the ProbComms table.

当你说查询返回2行时,我认为它应该是因为该问题有2个通信。如果要为学生返回问题,则无需查询ProbComms表,只需查询问题表。然后,如果要返回这些问题的通信,请查询ProbComms表。

For your loop, you need to loop through the problems and then within that loop, loop through the communications specific to that problem. Something very loosely like:

对于循环,您需要循环遍历问题,然后在该循​​环内循环执行特定于该问题的通信。一些非常松散的东西:

foreach (var p in Model.Student.Problem)
{
     <%= Html.Encode(p.ProblemInfoField) %>
     ...
     foreach (var c in p.ProbComms)
     {
        <%= Html.Encode(c.Communications.CommunicationInfoField) %>
         ...
     }
}

You do not need to select the ProbComms in the controller and send them to the view. They should already be linked. Only the student needs to be sent to the view.

您无需在控制器中选择ProbComms并将其发送到视图。他们应该已经联系起来。只有学生需要被发送到视图。

#1


1  

I have recently struggled greatly with many to many relationships in MVC. I've finally gotten mine working. I'd love to help you out, but do not fully understand your problem.

我最近在MVC中与很多关系斗争得很厉害。我终于让我的工作了。我很乐意帮助你,但不能完全理解你的问题。

When you say that the query returns 2 rows, I would think that it should since there are 2 communications for that problem. If you want to return problems for a student, you do not need to query the ProbComms table, just the Problem table. Then if you want to return communications for those problems, query the ProbComms table.

当你说查询返回2行时,我认为它应该是因为该问题有2个通信。如果要为学生返回问题,则无需查询ProbComms表,只需查询问题表。然后,如果要返回这些问题的通信,请查询ProbComms表。

For your loop, you need to loop through the problems and then within that loop, loop through the communications specific to that problem. Something very loosely like:

对于循环,您需要循环遍历问题,然后在该循​​环内循环执行特定于该问题的通信。一些非常松散的东西:

foreach (var p in Model.Student.Problem)
{
     <%= Html.Encode(p.ProblemInfoField) %>
     ...
     foreach (var c in p.ProbComms)
     {
        <%= Html.Encode(c.Communications.CommunicationInfoField) %>
         ...
     }
}

You do not need to select the ProbComms in the controller and send them to the view. They should already be linked. Only the student needs to be sent to the view.

您无需在控制器中选择ProbComms并将其发送到视图。他们应该已经联系起来。只有学生需要被发送到视图。