如何在MVC中对相关数据的集合进行排序?

时间:2015-03-12 19:07:17

标签: c# asp.net-mvc visual-studio asp.net-mvc-4 razor

我是MVC的新手,所以请保持温和。

以下是我的数据设置方式; 我在一个表中有一个订单列表。然后,每个订单都有一个步骤列表,用于在不同的表中完成该订单,这些表具有一对多的关系。

在我的订单索引页面上,我列出了所有有效订单。在详细信息页面上,我想列出该订单的每个步骤。我遇到的问题是步骤并不总是在表中。每个步骤都有一个步骤编号,用于确定步骤序列中的位置,但不是键值。

我想我错过了一些简单的东西。

提前感谢您的帮助。

这是我正在使用的内容;

OR_ORDER.cs

public partial class OR_ORDER
{
    public OR_ORDER()
    {
        this.OR_OP = new HashSet<OR_OP>();
    }

    public decimal NO { get; set; }
    public Nullable<decimal> MUSTERNO { get; set; }
    public Nullable<decimal> PRONO { get; set; }
    public Nullable<decimal> GRPNO { get; set; }
    public string NAME { get; set; }
    public string DESCR { get; set; }
    public string IDENT { get; set; }
    public Nullable<decimal> PPARTS { get; set; }
    public Nullable<decimal> SEQNO { get; set; }
    public Nullable<decimal> SOURCE { get; set; }
    public decimal STATUS { get; set; }

    public virtual ICollection<OR_OP> OR_OP { get; set; }
}

OR_OP.cs

public partial class OR_OP
{
    public decimal NO { get; set; }
    public decimal ORNO { get; set; }
    public string NAME { get; set; }
    public string DESCR { get; set; }
    public Nullable<decimal> APARTS { get; set; }
    public Nullable<decimal> ATE { get; set; }
    public Nullable<decimal> ATOTAL { get; set; }
    public Nullable<decimal> AWPLACE { get; set; }
    public Nullable<decimal> BPARTS { get; set; }
    public decimal CFLAG { get; set; }
    public Nullable<System.DateTime> CHTIME { get; set; }
    public Nullable<decimal> CPCOST { get; set; }
}
Controller中的

详情操作

    public ActionResult Details(decimal id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }

        OR_ORDER or_order = db.OR_ORDER.Find(id);

        //or_order.OR_OP = or_order.OR_OP.OrderBy(s => s.NAME);

        if (or_order == null)
        {
            return HttpNotFound();
        }
        return View(or_order);
    }

最后 Detials.cshtml 查看

@model Scheduler.Models.OR_ORDER

@{
    ViewBag.Title = "Details";
}

<h2>Details</h2>

<div>
<h4>JOB: @Model.NAME</h4>
<h4>@Model.DESCR</h4>
<hr />
<table>
    <tr>
        <th width="150px">
            Description
        </th>
        <th width ="150px">
            Time
        </th>
        <th width="150px">
            Op Info
        </th>
    </tr>

        @foreach (var item in Model.OR_OP)
        {                
            <tr>
                <td width="150px">
                    @Html.DisplayFor(modelitem => item.DESCR)
                </td>
                <td width="150px">
                    @Html.DisplayFor(modelitem => item.PTE)
                </td>
                <td width="150px">
                    @Html.DisplayFor(modelitem => item.OPINFO)
                </td>
            </tr>
        }

    </table>
</div>
<p>
    @*Html.ActionLink("Edit", "Edit", new { id = Model.NO }) |*@
    @Html.ActionLink("Back Job List", "Index")
</p>

2 个答案:

答案 0 :(得分:2)

这就是所谓的&#34;艰苦学习课程&#34;。您看到的大多数示例代码只是将您的实体从实体框架直接发送到视图。这有很多问题。

首先,您已经发现,您无法以这种方式真正控制实体模型的其他部分。例如,您无法轻易地告诉模型对导航属性进行排序。至少在这一点上没有。

其次,您也会将视图与数据模型紧密耦合,并且您的视图可能没有完全相同的结构。

第三,您的视图与数据模型之间可能存在安全性或验证差异。

最终,你想要的是一个视图模型。这是一个根据视图需求量身定制的模型,只包含视图所需的数据。您现在可以以任何格式,结构,顺序或任何您想要的方式将数据复制到该ViewModel。

另一种方法是在视图中执行排序逻辑,这可能是某些人可以接受的。我不这么认为。

答案 1 :(得分:0)

您给我们的代码中最简单(最少侵入性)的方法是将LINQ表达式添加到模型中:

@foreach (var item in Model.OR_OP.OrderBy(c => c.NO)) // I wasn't sure what
                                                      // property to use

然而,在你的模型中使用那个逻辑有点乱。

您还可以将属性类型从HashSet<OR_PP>调整为List<OR_OP>,如果您有List<>.Sort()则调用IComparer,或者只使用您已注释掉的内容,使用与我所做的相同的LINQ调用,以及.ToList()它。

最好的解决方案,尽管不是非常漂亮,可能是添加另一个具有此排序集合的额外属性的类。您将在两个类之间拥有冗余数据,但这将是任何选项中最易维护的数据。

您评论的行的问题是HashSet<>未订购。它们必须在实践中,因为RAM是,并且它们每次都会以相同的顺序枚举,但理论上,不会以任何方式保证订单。但是,List<>确实支持排序,它还实现了ICollection<T>,这是EF集合属性的要求。


在你的评论之后,听起来你有一个更基本的问题 - 听起来你的操作存储为字符串。

快速修复,我绝对讨厌这个问题,就是按解析进行排序。

@foreach (var item in Model.OR_OP.OrderBy(c => int.Parse(c.NO))) // I wasn't sure what
                                                                 // property to use

那是糟糕。除非你拥有,否则不要这样做,即使你这样做,也要使用视图模型。

实际上,您应该更改数据库和财产的类型。