【问题标题】:MVC 5 EF 6 - How to Search a Table Using Related Table Object CriteriaMVC 5 EF 6 - 如何使用相关表对象条件搜索表
【发布时间】:2016-05-17 19:59:35
【问题描述】:

我需要显示一个 PO 请求的结果表,其中包括 PO 项目(这部分是我想出来的),并为所有显示的项目提供搜索功能(这部分我主要想出来)。

使用下面的代码,这是一个稍微精简的版本,我能够显示我需要的数据,并且我能够搜索几乎所有我需要的数据,只要它是来自 PORequests 模型的数据(这是“父模型”)。当我尝试使用“子模型”POItems 进行搜索时,无法访问实际对象(ID、描述等)。这是使用 DatabaseFirst 模型和 EF6.x DbContextGenerator 构建的。

//POItemData ViewModel
using FinanceSearch.Models;
namespace FinanceSearch.ViewModels
{
    public class POItemData
    {
        public PagedList.IPagedList<PORequest> PORequests { get; set; }
        public PagedList.IPagedList<POItem> POItems { get; set; }
    }
}

//POItems Model
namespace FinanceSearch.Models
{
    using System;
    using System.Collections.Generic;

    public partial class POItem
    {
        public int ID { get; set; }
        public int Amount { get; set; }
        public string Description { get; set; }

        public virtual PORequest PORequest { get; set; }
    }
}

//PORequest Model
namespace FinanceSearch.Models
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;

    public partial class PORequest
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public PORequest()
        {
            this.POAttachments = new HashSet<POAttachment>();
            this.POItems = new HashSet<POItem>();
        }

        //other relevant stuff

        public virtual ICollection<POItem> POItems { get; set; }

    }
}


//Controller
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using FinanceSearch.Models;
using PagedList;
using System.Web.UI.WebControls;
using System.Data.Entity.SqlServer;
using FinanceSearch.ViewModels;

namespace FinanceSearch.Controllers
{
    public class PORequestsController : Controller
    {
        private Finance db = new Finance();



        public ActionResult Index(int? id, int? page, string sortOrder, string currentFilter, string poNumber,
           string AppropNumber, string ContractNumber, string ItemDescription)
        {

            ViewBag.CurrentSort = sortOrder;
            ViewBag.POSortParm = String.IsNullOrEmpty(sortOrder) ? "PONumber_desc" : "";
            ViewBag.AppropNumberSortParm = sortOrder == "AppropNumber" ? "AppropNumber_desc" : "AppropNumber";
            ViewBag.ContractNumberSortParm = sortOrder == "ContractNumber" ? "ContractNumber_desc" : "ContractNumber";


            if (poNumber != null)
            {
                page = 1;
            }
            else
            {
                ponumber = currentFilter;
            }

            //int pageSize = 3;
            int pageNumber = (page ?? 1);

            var viewModel = new POItemData();

            viewModel.PORequests = db.PORequests
               .Include(i => i.POItems)
               .OrderBy(i => i.ID).ToPagedList(pageNumber, 5);

            if (!String.IsNullOrEmpty(poNumber))
            {
                viewModel.PORequests = viewModel.PORequests.Where(s => s.PONumber.Contains(ponumber)).ToPagedList(pageNumber, 5);
            }
            if (!string.IsNullOrEmpty(AppropNumber))
            {
                viewModel.PORequests = viewModel.PORequests.Where(x => x.AppropNumber.Contains(AppropNumber)).ToPagedList(pageNumber, 5);
            }
            if (!string.IsNullOrEmpty(ContractNumber))
            {
                viewModel.PORequests = viewModel.PORequests.Where(x => x.ContractNumber.Contains(ContractNumber)).ToPagedList(pageNumber, 5);
            }
            if (!string.IsNullOrEmpty(ItemDescription))
            {

            }

在 ItemDescription if 语句中,类似以下的内容会很好:

if (!string.IsNullOrEmpty(ItemDescription))
{
viewModel.PORequests = viewModel.PORequests.Where(x => x.POItems.Description.Contains(ItemDescription)).ToPagedList(pageNumber, 5);
}

x.POItems.Description 部分在这个意义上不存在。显然与它是一个列表有关。继续剩余代码...

            switch (sortOrder)
            {
                case "PONumber_desc":
                    viewModel.PORequests = viewModel.PORequests.OrderByDescending(s => s.PONumber).ToPagedList(pageNumber, 5);
                    break;
                case "AppropNumber":
                    viewModel.PORequests = viewModel.PORequests.OrderBy(s => s.AppropNumber).ToPagedList(pageNumber, 5);
                    break;
                case "AppropNumber_desc":
                    viewModel.PORequests = viewModel.PORequests.OrderByDescending(s => s.AppropNumber).ToPagedList(pageNumber, 5);
                    break;
                case "ContractNumber":
                    viewModel.PORequests = viewModel.PORequests.OrderBy(s => s.ContractNumber).ToPagedList(pageNumber, 5);
                    break;
                case "ContractNumber_desc":
                    viewModel.PORequests = viewModel.PORequests.OrderByDescending(s => s.ContractNumber).ToPagedList(pageNumber, 5);
                    break;
                default: 
                    viewModel.PORequests = viewModel.PORequests.OrderBy(s => s.PONumber).ToPagedList(pageNumber, 5);
                    break;
            }


            return View(viewModel);
        }

在上面的代码中,我也包含了我的分页和排序内容,因为在我遇到的教程和答案中,这似乎对结果有所不同,并且是该项目所必需的。

下面是我用来显示结果的索引/视图:

//View    (Index)    
@model FinanceSearch.ViewModels.POItemData
@using PagedList.Mvc;
<link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />

@{
    ViewBag.Title = "PORequests";
}

<h2>Finance</h2>

@*<p>
    @Html.ActionLink("Create New", "Create")
</p>*@

<p>
    <button class="btn btn-default" data-toggle="collapse" href="#MainFilter" @*data-target="#MainFilter"*@ aria-multiselectable="true" aria-expanded="true">Filter By...</button>
</p>

@*<div id="accordion" role="tablist" aria-multiselectable="true">*@
@using (Html.BeginForm("Index", "PORequests", FormMethod.Get))
{
    <div id="MainFilter" class="collapse">

        <table class="table-responsive">
            <tr>
                <td>
                    Item: 
                </td>
                <td>
                    @Html.TextBox("ItemDescription", ViewBag.CurrentFilter as string) //this is where the user would search items using a string
                </td>
            </tr>
            <tr>
                <td>
                    PO #:
                </td>
                <td>
                    @Html.TextBox("PONumber", ViewBag.CurrentFilter as string)
                </td>
            </tr>
        </table>
        <br />
        <p>
            <button class="btn btn-primary btn-sm" data-parent="#MainFilter" data-toggle="collapse" href="#SubFilterPOInfo" @*data-target="#SubFilterPOInfo"*@>Filter by PO Info...</button>
        </p>

        <div id="SubFilterPOInfo" class="collapse">
            <table class="table-responsive">
                <tr>
                    <td>
                        AppropNumber:
                    </td>
                    <td>
                        @Html.TextBox("AppropNumber", ViewBag.CurrentFilter as string)
                    </td>
                </tr>
                <tr>
                    <td>
                        Contract Number:
                    </td>
                    <td>
                        @Html.TextBox("ContractNumber", ViewBag.CurrentFilter as string)
                    </td>
                </tr>
            </table>
        </div>

}

<div style="overflow-x: scroll">

    <table class="table" style="white-space:nowrap">

        <tr>
            <th></th>
            <th></th>
            <th>
                @Html.ActionLink("PONumber", "Index", new { sortOrder = ViewBag.POSortParm, currentFilter = ViewBag.CurrentFilter })
            </th>
            <th>
                @Html.ActionLink("AppropNumber", "Index", new { sortOrder = ViewBag.AppropNumberSortParm, currentFilter = ViewBag.CurrentFilter })
            </th>
            <th>
                @Html.ActionLink("ContractNumber", "Index", new { sortOrder = ViewBag.ContractNumberSortParm, currentFilter = ViewBag.CurrentFilter })
            </th>
        </tr>

        @foreach (var item in Model.PORequests)
            {
            <tr>
                <td>
                    @*@Html.ActionLink("Edit", "Edit", new { id = item.ID }) |*@
                    @Html.ActionLink("Details", "Details", new { id = item.ID }) |
                    @*@Html.ActionLink("Delete", "Delete", new { id = item.ID })*@
                </td>
                <td>
                    //I am able to list the related items in the PORequests table
                    @foreach (var poitem in item.POItems)
                    {
                        @poitem.Description<br />
                    }

                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.PONumber)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.AppropNumber)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.ContractNumber)
                </td>

            </tr>

        }
    </table>

</div>
<br />
//paging and sorting stuff
    Page @(Model.PORequests.PageCount < Model.PORequests.PageNumber ? 0 : Model.PORequests.PageNumber) of @Model.PORequests.PageCount
    @Html.PagedListPager(Model.PORequests, page => Url.Action("Index", new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }))

总结一下:

我似乎不明白如何使用变量 ItemDescription 在 POItems 列表中进行搜索,并获取包含 POItem 表作为相关对象的 PORequest 表来显示结果。我的其他搜索都按预期运行。

我已经搜索过,特别是在这个网站上,但是任何类似的问题都涉及它的视图端,它只是显示列表中的每个项目,我可以这样做,或者创建/编辑功能,或者,也许,它们超出了我对 MVC 的理解,它们似乎不是解决方案。

这里有几个这样的例子:

MVC Code First: One-to-many relationship between own model and SimpleMembership user

EntityFramework 6. How to get related objects?

https://stackoverflow.com/questions/26372533/add-the-list-of-object-to-parent-object-using-mvc-5-and-ef-6

任何帮助都会非常感谢

【问题讨论】:

  • 您应该在内部使用任何查询,例如:viewModel.PORequests = viewModel.PORequests.Where(x => x.POItems.Any(i => i.Description.Contains(ItemDescription)))。 ToPagedList(pageNumber, 5);
  • @t.enix 哎呀,我没有注意到你的评论。随意添加它作为答案,我会删除我的。

标签: c# asp.net asp.net-mvc entity-framework


【解决方案1】:

深入到搜索表达式中的项目:

if (!string.IsNullOrEmpty(ItemDescription))
{
    viewModel.PORequests = viewModel.PORequests.Where(x => x.POItems
        .Any(i => i.Description.Contains(ItemDescription)))
        .ToPagedList(pageNumber, 5);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-11
    • 2016-11-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多