在MVC Razor中从数据库获取数据时LINQ查询性能问题

在MVC Razor中从数据库获取数据时LINQ查询性能问题,linq,asp.net-mvc-4,razor,linq-to-sql,Linq,Asp.net Mvc 4,Razor,Linq To Sql,问题陈述: 我正在尝试使用Linq查询将数据库中的多表数据绑定到视图,这需要更多的时间。我在数据库中有大约10000条记录。有人建议使用IQueryable而不是IEnumerable,但它是否会影响我当前的代码(在视图和控制器中)??或者不使用它,我能做到这一点吗 我应该怎么做才能提高加载结果的性能?? 我做错了什么?? 请给我建议一些更好的方法…… 控制器: public ActionResult Index() { var result = (from pr in

问题陈述: 我正在尝试使用Linq查询将数据库中的多表数据绑定到视图,这需要更多的时间。我在数据库中有大约10000条记录。有人建议使用IQueryable而不是IEnumerable,但它是否会影响我当前的代码(在视图和控制器中)??或者不使用它,我能做到这一点吗

我应该怎么做才能提高加载结果的性能?? 我做错了什么?? 请给我建议一些更好的方法……

控制器:

public ActionResult Index()
    {
        var result = (from pr in db.Prod.AsEnumerable()
                      join s in db.Shift.AsEnumerable() on pr.Shift equals s.ShiftID
                      join m in db.Module.AsEnumerable() on pr.Module equals m.ModuleID
                      select new GlobalModel()
                      {
                          prodModelIndex = pr,
                          prodModel = prodModel,
                          shiftModel = s,
                          moduleModel = m,
                          ddlShift = objTransactionGeneralController.GetAllShift(),
                          ddlModule = objTransactionGeneralController.GetAllModule()

                      }).ToList();
    return PartialView(result);

    }





   public TransGeneralModel GetAllModule()
    {

        objTransGeneralModel.ddlModule = (from m in db.Module.AsEnumerable()
                                           select new SelectListItem
                                           {
                                               Value = m.ModuleID.ToString(),
                                               Text = m.ModuleName,
                                           }).ToList();


        return objTransGeneralModel;
    }

    public TransGeneralModel GetAllShift()
    {

        objTransGeneralModel.ddlShift = (from s in db.Shift.AsEnumerable()
                                          select new SelectListItem
                                          {
                                              Value = s.ShiftID.ToString(),
                                              Text = s.ShiftName,
                                          }).ToList();


        return objTranGeneralModel;
    }
@model IEnumerable<SIA.Models.Trans.GlobalModel>

@using GridMvc.Html

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
    ViewBag.Title = "Index";

    }

    <link rel="stylesheet" href="@Url.Content("~/Content/jquery.dataTables.min.css")">
    <script src="@Url.Content("~/Scripts/jquery-2.1.1.min.js")"></script>


    <h2>Details</h2>
    <hr />

    <div style="width: 1000px; padding-left: 70px">
        @Html.Partial("Create")
        <br />
    </div>

    <h5 class="pull-right">
        <b class="fa fa-keyboard-o" style="color: blue"></b>
        @Ajax.ActionLink("Edit", "ProdEdit", "Prod", new { }, new AjaxOptions
    {
        InsertionMode = InsertionMode.Replace,
        UpdateTargetId = "prod-details",
        HttpMethod = "GET",
    }, new { style = "color:blue" })
    </h5>

    <br />
    @using (Html.BeginForm())
    {
        @Html.AntiForgeryToken()
        @Html.ValidationSummary(true)
        if (Model.FirstOrDefault().prodModelIndex != null)
        { 

        <div id="prod-details">
            <table class="table table-striped" id="tblProdDetails">
                <thead>
                    <tr>

                        <th>
                            @Html.DisplayNameFor(model => model.FirstOrDefault().prodModelIndex.ProdID)
                        </th>
                        <th>
                            @Html.DisplayNameFor(model => model.FirstOrDefault().prodModelIndex.Date)
                        </th>
                        <th>
                            @Html.DisplayNameFor(model => model.FirstOrDefault().prodModelIndex.Module)
                        </th>
                        <th>
                            @Html.DisplayNameFor(model => model.FirstOrDefault().productionModelIndex.Shift)
                        </th>

                        <th>
                            @Html.DisplayNameFor(model => model.FirstOrDefault().prodModelIndex.Hour)
                        </th>
                        <th>
                            @Html.DisplayNameFor(model => model.FirstOrDefault().prodModelIndex.Output)
                        </th>

                    </tr>
                </thead>
                <tbody>
                    @foreach (var item in Model)
                    {
                        <tr id="customer-row-@item.prodModelIndex.ProdID">


                            <td>
                                @Html.DisplayFor(modelItem => item.prodModelIndex.ProdID)
                            </td>
                            <td>
                                @Html.DisplayFor(modelItem => item.prodModelIndex.Date)
                            </td>
                            <td>
                                @Html.DisplayFor(modelItem => item.moduleModel.ModuleName)
                            </td>
                            <td>
                                @Html.DisplayFor(modelItem => item.shiftModel.ShiftName)
                                @Html.HiddenFor(modelItem => item.prodModelIndex.Shift)
                            </td>

                            <td>
                                @Html.DisplayFor(modelItem => item.prodModelIndex.Hour)
                            </td>
                            <td>
                                @Html.DisplayFor(modelItem => item.prodModelIndex.Output)
                            </td>
                        </tr>
                    }
                </tbody>
            </table>

        </div>
        }
    }

    <script>

        $(document).ready(function () {

            $('#tblProdDetails').dataTable({
                "order": [[1, "desc"], [3, "asc"]]

            });

        });
    </script>

    @section Scripts {
        @Scripts.Render("~/bundles/jqueryval")
        @Scripts.Render("~/Scripts/jquery.dataTables.min.js")
        <script type='text/javascript'>
            $(function () {
                $('.datepicker').datepicker({
                    format: "dd M yyyy",
                }).on('changeDate', function (e) {
                    $(this).datepicker('hide');
                });
            })

        </script>
    }
查看:

public ActionResult Index()
    {
        var result = (from pr in db.Prod.AsEnumerable()
                      join s in db.Shift.AsEnumerable() on pr.Shift equals s.ShiftID
                      join m in db.Module.AsEnumerable() on pr.Module equals m.ModuleID
                      select new GlobalModel()
                      {
                          prodModelIndex = pr,
                          prodModel = prodModel,
                          shiftModel = s,
                          moduleModel = m,
                          ddlShift = objTransactionGeneralController.GetAllShift(),
                          ddlModule = objTransactionGeneralController.GetAllModule()

                      }).ToList();
    return PartialView(result);

    }





   public TransGeneralModel GetAllModule()
    {

        objTransGeneralModel.ddlModule = (from m in db.Module.AsEnumerable()
                                           select new SelectListItem
                                           {
                                               Value = m.ModuleID.ToString(),
                                               Text = m.ModuleName,
                                           }).ToList();


        return objTransGeneralModel;
    }

    public TransGeneralModel GetAllShift()
    {

        objTransGeneralModel.ddlShift = (from s in db.Shift.AsEnumerable()
                                          select new SelectListItem
                                          {
                                              Value = s.ShiftID.ToString(),
                                              Text = s.ShiftName,
                                          }).ToList();


        return objTranGeneralModel;
    }
@model IEnumerable<SIA.Models.Trans.GlobalModel>

@using GridMvc.Html

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
    ViewBag.Title = "Index";

    }

    <link rel="stylesheet" href="@Url.Content("~/Content/jquery.dataTables.min.css")">
    <script src="@Url.Content("~/Scripts/jquery-2.1.1.min.js")"></script>


    <h2>Details</h2>
    <hr />

    <div style="width: 1000px; padding-left: 70px">
        @Html.Partial("Create")
        <br />
    </div>

    <h5 class="pull-right">
        <b class="fa fa-keyboard-o" style="color: blue"></b>
        @Ajax.ActionLink("Edit", "ProdEdit", "Prod", new { }, new AjaxOptions
    {
        InsertionMode = InsertionMode.Replace,
        UpdateTargetId = "prod-details",
        HttpMethod = "GET",
    }, new { style = "color:blue" })
    </h5>

    <br />
    @using (Html.BeginForm())
    {
        @Html.AntiForgeryToken()
        @Html.ValidationSummary(true)
        if (Model.FirstOrDefault().prodModelIndex != null)
        { 

        <div id="prod-details">
            <table class="table table-striped" id="tblProdDetails">
                <thead>
                    <tr>

                        <th>
                            @Html.DisplayNameFor(model => model.FirstOrDefault().prodModelIndex.ProdID)
                        </th>
                        <th>
                            @Html.DisplayNameFor(model => model.FirstOrDefault().prodModelIndex.Date)
                        </th>
                        <th>
                            @Html.DisplayNameFor(model => model.FirstOrDefault().prodModelIndex.Module)
                        </th>
                        <th>
                            @Html.DisplayNameFor(model => model.FirstOrDefault().productionModelIndex.Shift)
                        </th>

                        <th>
                            @Html.DisplayNameFor(model => model.FirstOrDefault().prodModelIndex.Hour)
                        </th>
                        <th>
                            @Html.DisplayNameFor(model => model.FirstOrDefault().prodModelIndex.Output)
                        </th>

                    </tr>
                </thead>
                <tbody>
                    @foreach (var item in Model)
                    {
                        <tr id="customer-row-@item.prodModelIndex.ProdID">


                            <td>
                                @Html.DisplayFor(modelItem => item.prodModelIndex.ProdID)
                            </td>
                            <td>
                                @Html.DisplayFor(modelItem => item.prodModelIndex.Date)
                            </td>
                            <td>
                                @Html.DisplayFor(modelItem => item.moduleModel.ModuleName)
                            </td>
                            <td>
                                @Html.DisplayFor(modelItem => item.shiftModel.ShiftName)
                                @Html.HiddenFor(modelItem => item.prodModelIndex.Shift)
                            </td>

                            <td>
                                @Html.DisplayFor(modelItem => item.prodModelIndex.Hour)
                            </td>
                            <td>
                                @Html.DisplayFor(modelItem => item.prodModelIndex.Output)
                            </td>
                        </tr>
                    }
                </tbody>
            </table>

        </div>
        }
    }

    <script>

        $(document).ready(function () {

            $('#tblProdDetails').dataTable({
                "order": [[1, "desc"], [3, "asc"]]

            });

        });
    </script>

    @section Scripts {
        @Scripts.Render("~/bundles/jqueryval")
        @Scripts.Render("~/Scripts/jquery.dataTables.min.js")
        <script type='text/javascript'>
            $(function () {
                $('.datepicker').datepicker({
                    format: "dd M yyyy",
                }).on('changeDate', function (e) {
                    $(this).datepicker('hide');
                });
            })

        </script>
    }
@model IEnumerable
@使用GridMvc.Html
@{
Layout=“~/Views/Shared/_Layout.cshtml”;
ViewBag.Title=“Index”;
}
细节

@Html.Partial(“创建”)
@ActionLink(“Edit”、“ProdEdit”、“Prod”、new{}、new AjaxOptions { InsertionMode=InsertionMode.Replace, UpdateTargetId=“产品详细信息”, HttpMethod=“GET”, },新{style=“color:blue”})
@使用(Html.BeginForm()) { @Html.AntiForgeryToken() @Html.ValidationSummary(true) if(Model.FirstOrDefault().prodModelIndex!=null) { @DisplayNameFor(model=>model.FirstOrDefault().prodModelIndex.ProdID) @DisplayNameFor(model=>model.FirstOrDefault().prodModelIndex.Date) @DisplayNameFor(model=>model.FirstOrDefault().prodModelIndex.Module) @DisplayNameFor(model=>model.FirstOrDefault().productionModelIndex.Shift) @DisplayNameFor(model=>model.FirstOrDefault().prodModelIndex.Hour) @DisplayNameFor(model=>model.FirstOrDefault().prodModelIndex.Output) @foreach(模型中的var项目) { @DisplayFor(modelItem=>item.prodModelIndex.ProdID) @DisplayFor(modelItem=>item.prodModelIndex.Date) @DisplayFor(modelItem=>item.moduleModel.ModuleName) @DisplayFor(modelItem=>item.shiftModel.ShiftName) @HiddenFor(modeleItem=>item.prodModelIndex.Shift) @DisplayFor(modelItem=>item.prodModelIndex.Hour) @DisplayFor(modelItem=>item.prodModelIndex.Output) } } } $(文档).ready(函数(){ $('#tblProdDetails')。数据表({ “订单”:[[1,“说明”],[3,“asc”]] }); }); @节脚本{ @Scripts.Render(“~/bundles/jqueryval”) @Scripts.Render(“~/Scripts/jquery.dataTables.min.js”) $(函数(){ $('.datepicker').datepicker({ 格式:“dd M yyy”, }).on('changeDate',函数(e){ $(this.datepicker('hide'); }); }) }
首先,当您调用像
ToList()
AsEnumerable()
FirstOrDefault()
这样的方法时,它将在数据库上执行查询。在您的情况下,最好删除它们,以使用
连接来点击单个查询

var result = (from pr in db.Prod
                      join s in db.Shift on pr.Shift equals s.ShiftID
                      join m in db.Module on pr.Module equals m.ModuleID
                      select new GlobalModel()
                      {
                          prodModelIndex = pr,
                          prodModel = prodModel,
                          shiftModel = s,
                          moduleModel = m

                      }).ToList();

如果表由外键引用,则无需联接。您可以像这样直接访问引用的记录

var result = (from pr in db.Prod
                      select new GlobalModel()
                      {
                          prodModelIndex = pr,
                          prodModel = prodModel,
                          shiftModel = pr.Shift,
                          moduleModel = pr.Module     
                      }).ToList();
TL;DR

  • 使用
    .Where
    筛选主表(Prod),或者至少使用
    .Take()
    将行数限制为屏幕上显示的正常行数
  • 删除
    .AsEnumerable()
    -您正在将整个表具体化到内存中
  • 向表中添加外键,重新生成DBML,并使用导航而不是显式联接
  • 请注意在
    Select
    projection中输入的内容-
    ddlShift=objTransactionGeneralController。结果集中的每一行都将调用GetAllShift()
详细信息

通过将
.AsEnumerable()
应用于您的集合,如:

var result = (from pr in db.Prods.AsEnumerable()
      join s in db.Shifts.AsEnumerable() on pr.ShiftID equals s.ShiftId
      join m in db.Modules.AsEnumerable() on pr.ModuleID equals m.ModuleId
      select new ...
您当前的代码会导致对Sql Server的3个显式查询,每个查询都会将整个表加载到内存中:(例如,使用
Sql Profiler
,或
LinqPad
,等等)

考虑到您根本没有
WHERE
谓词,这可能不会比加入数据库慢多少。然而,一般来说,这样做根本不是一个好主意,因为:

  • 通过应用
    .AsEnumerable()
    ,您将剥夺Linq2Sql将
    IQueryable
    表达式树解析为本机Sql的能力。通常,在数据库中进行连接和筛选会比在内存中进行更快,并且需要的内存更少。假设
    Prod
    Shift
    Module
    Lin
    
    SELECT TOP 1000 [t0].[ProdID], [t0].[ShiftID], [t0].[ModuleID], [t1].[ShiftId] AS [ShiftId2], [t2].[ModuleId] AS [ModuleId2]
    FROM [dbo].[Prod] AS [t0]
    INNER JOIN [dbo].[Shift] AS [t1] ON [t0].[ShiftID] = ([t1].[ShiftId])
    INNER JOIN [dbo].[Module] AS [t2] ON [t0].[ModuleID] = ([t2].[ModuleId])
    WHERE [t0].[ProdID] BETWEEN 5 AND 10;