ASP.NET MVC示例(三)

  • ASP.NET MVC示例(三)已关闭评论
  • 290 views
  • A+
所属分类:C#.NET 编程技术
【腾讯云】11.11 云上盛惠,云产品限时抢购,1核2G云服务器首年88元

分页SQL语句

完成上面的代码,分页效果已经出来了:

ASP.NET MVC示例(三)

下面,我们使用第三方Express Profiler工具来检查EF生成的数据库分页SQL语句。

 

首先下载工具:

http://expressprofiler.codeplex.com/

 

打开Express Profiler,在Server文本框中输入(LocalDb)\MSSQLLocalDB,如果你使用的VS2013,这个字符串可能是:(LocalDb)\v11.0,点击绿色的启用按钮:

ASP.NET MVC示例(三)

运行我们的示例,转到学生列表页面,然后清空Express Profiler中的全部显示,再点击第二页:

ASP.NET MVC示例(三)

可以看到这里有3次SQL查询,这个和我们的心理预期是一样的:

  1. 第一次SQL查询:总记录数

SELECT

[GroupBy1].[A1] AS [C1]

FROM ( SELECT

COUNT(1) AS [A1]

FROM [dbo].[Students] AS [Extent1]

)  AS [GroupBy1]

go

 

对应的C#代码:

var students = db.Students as IQueryable<Student>;

var recordCount = students.Count();

 

  1. 第二次SQL查询:所学专业集合(去除重复)

SELECT

[Distinct1].[Major] AS [Major]

FROM ( SELECT DISTINCT

[Extent1].[Major] AS [Major]

FROM [dbo].[Students] AS [Extent1]

)  AS [Distinct1]

go

 

对应的C#代码:

var majors = db.Students.OrderBy(m => m.Major).Select(m => m.Major).Distinct();

 

  1. 第三次SQL查询:分页数据

SELECT

[Extent1].[ID] AS [ID],

[Extent1].[Name] AS [Name],

[Extent1].[Gender] AS [Gender],

[Extent1].[Major] AS [Major],

[Extent1].[EntranceDate] AS [EntranceDate],

[Extent1].[Job] AS [Job]

FROM [dbo].[Students] AS [Extent1]

ORDER BY [Extent1].[Name] ASC

OFFSET 3 ROWS FETCH NEXT 3 ROWS ONLY

go

 

对应的C#代码:

return students.OrderBy(m => m.Name)

.Skip(pageIndex * PAGE_SIZE)

.Take(PAGE_SIZE).ToList();

 

这个查询顺序也和前面的EF代码的执行顺序一模一样,可以再回过头看下控制器Index方法。

 

同时处理表单检索和数据库分页

不过目前遇到点难题,我们希望实现如下两个功能:

  1. 点击分页链接时会发出HTTP POST请求,在请求参数中带上表单检索值。
  2. 表单检索时,在请求参数中带上当前所在的分页索引。

 

实现这两个功能才算完善,否则表单检索时如果丢失分页参数,就会回到第一页;而分页时如果丢失表单参数,就会清空表单输入框。

 

是不是开始怀念WebForms了,在WebForms中整个页面都被包含在一个表单中,因此回发时根本不需要考虑哪些参数后台需要。而MVC中这个就需要我们操心了,毕竟在灵活性的面前,便利性就会有所打折。

 

我们采取的办法是扩充前面的form标签,加入PageIndex隐藏字段,然后点击分页链接时提交表单即可:

using (Html.BeginForm("Index", "Students", FormMethod.Post, new { id = "searchForm" }))
{
    @Html.AntiForgeryToken()
    <p>
        所学专业: @Html.DropDownList("Major",
ViewBag.MajorList as IEnumerable<SelectListItem>, "全部")
        姓名: @Html.TextBox("Name")
        <input type="hidden" id="PageIndex" name="PageIndex" value="0" />
        <input type="button" id="searchButton" value="检索" />
    </p>
}

注册JavaScript脚本来处理点击[检索]按钮和分页链接:

@section scripts {
    <script>
        function submitForm(pagenumber) {
            pagenumber = parseInt(pagenumber, 10);
            $('#PageIndex').val(pagenumber - 1);
            $('#searchForm').submit();
        }
 
        $(function () {
 
            $('#searchButton').click(function () {
                submitForm($('#pagebar .currentpagenumber').text());
            });
 
            $('#pagebar .pagenumber').click(function () {
                submitForm($(this).text());
            });
 
        });
    </script>
}

现在看下效果,首先检索所学专业:

ASP.NET MVC示例(三)

然后点击第二页,会发出一个POST请求:

ASP.NET MVC示例(三)

可以看到本次请求,上面的用户输入和PageIndex都发送到了控制器处理方法:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(string Major, string Name, int PageIndex)
{
       var students = db.Students as IQueryable<Student>;
       if (!String.IsNullOrEmpty(Name))
       {
              students = students.Where(m => m.Name.Contains(Name));
       }
 
       if (!String.IsNullOrEmpty(Major))
       {
              students = students.Where(m => m.Major == Major);
       }
 
 
       var recordCount = students.Count();
       var pageCount = GetPageCount(recordCount);
       if (PageIndex >= pageCount && pageCount >= 1)
       {
              PageIndex = pageCount - 1;
       }
 
       students = students.OrderBy(m=>m.Name)
            .Skip(PageIndex * PAGE_SIZE).Take(PAGE_SIZE);
 
       ViewBag.PageIndex = PageIndex;
       ViewBag.PageCount = pageCount;
 
       ViewBag.MajorList = GetMajorList();
       return View(students.ToList());
}

这里需要注意一点:先进行表单过滤,然后执行获取总记录数的查询,最后再获取分页数据。这个顺序不能变,因为表单过滤后总记录才能确定下来。

  • 我的微信
  • 这是我的微信扫一扫
  • weinxin
  • 我的微信公众号
  • 我的微信公众号扫一扫
  • weinxin