开发工具与关键技术:Visual Studio 2015 LINQ
作者:孙水兵
撰写时间:2019年6月3
一、 达到的效果
在数据表格中要有线路名称、线路表号、起点站编号、起点站名称、终点站编号、终点站名称、里程、方向、所属车站编号、所属车站信息、所属区域、备注、停开这些字段的数据。除此之外,在数据表格的上方有一个线路编号/名称的input框,可以在input框中输入线路编号或者名称然后点击查询,可以查出相对应的数据。
二、 涉及到的表格:线路表(SYS_Circuit)、站点表(SYS_Station )、站点明细表(SYS_StationDetail)、线路站点类型表(SYS_CircuitStationType)
在这些表格中,线路表、站点表、线路站点类型表都是根据站点明细表连接起来的,其中线路站点类型表中的线路站点类型ID(CircuitStationTypeID)等于1时,表示的站点类型为起点站,线路站点类型表中的线路站点类型ID(CircuitStationTypeID)等于2时,表示的站点类型为终点站。
三、 代码(建议和我以前的文章:简单使用layui完成数据表格对比查看)
HTML代码
HTML代码只需要在合适的地方放置一个table标签,id和lay-filter都写上即可。查询按钮和查询的input框另外写。
<div class="container-fluid">
<div class="row">
<!--线路信息-->
<div class="col-12 p-1 ">
<div class="card" id="Circuit">
<div class="card-header"><span>线路详细情况</span></div>
<div class="card-body pt-2">
<div class="row pl-5 flex-lg-wrap mt-2">
<div class="col-10">
<form class="form-inline form-row">
<label class="col-form-label mr-2" for="searchPlanCircuitCode">线路编号/名称:</label>
<input class="form-control form-control-sm mr-3" id="searchPlanCircuitCode" name="searchPlanCircuitCode" />
@*在超小(手机等移动端)上强制换行并设置边距*@
<div class="w-100 mb-2 d-inline d-sm-none"></div>
@*按钮组*@
<div class="form-group">
<button type="button" class="btn btn-sm btn-primary mr-4" onclick="searchTabCircuit()">查询</button>
<button type="button" class="btn btn-sm btn-primary mr-lg-3" id="InsertCircuit">添加</button>
<button type="button" class="btn btn-sm btn-primary mr-4">打印</button>
<button type="button" class="btn btn-sm btn-danger mr-4 " onclick="deleteCircuit()">批量删除</button>
</div>
</form>
</div>
<div class="col-2">
<button type="button" class="btn btn-sm btn-secondary" id="quit"><i class="zi zi_circleLeftLong m-1" zico="指左圆箭头长"></i>退出</button>
</div>
</div>
<div class="row">
<div class="col-12">
<table id="tabCircuit" lay-filter="tabCircuit"></table>
</div>
</div>
</div>
</div>
</div>
</div>
JS代码
关于如何用layui插件搭建基础的数据表格可以查看我以前的文章:简单使用layui完成数据表格。稍微有点不同的是这里涉及到了条件查询,要使用layui中table模块中的表格重载。因此需要在表格的分页的下方加上data[],除此之外还需要将表格中的URL注释或者剪切到表格重载中。在条件查询的方法中获取到查询的input框的值并用searchCircuitNameNum接收,然后判断searchCircuitNameNum是否为undefined,如果是,让searchCircuitNameNum为空字符串。然后调用表格的重载,在重载的方法中调用控制器中查询的方法,利用where将获取到的searchCircuitNameNum的值传入控制器。Page:{curr:1}表示重新从第一页开始。(建议先从数据库中查出了数据在写条件查询)
$(function () {
layui.use(['layer', 'table'], function () {
layer = layui.layer;
layuiTable = layui.table;
layuiForm = layui.form;
//线路表
tabCircuit = layuiTable.render({
elem: "#tabCircuit",
//url: "/BusinessManagement/CircuitManagement/SelectCircuitAll",
cellMinWidth: 80,
cols: [[
{ type: 'checkbox' },
{ type: 'numbers', title: '序号' },
{ field: 'CircuitID', title: 'CircuitID', hide: true },//hide:true 隐藏列
{ field: 'CircuitName', title: '线路名称', align: 'center' },
{ field: 'CircuitNumber', title: '线路编号', align: 'center' },
{ field: 'StartStationCode', title: '起点站编号', align: 'center' },
{ field: 'StartStationName', title: '起点站名称', align: 'center' },
{ field: 'EndStationCode', title: '终点站编号', align: 'center' },
{ field: 'EndStationName', title: '终点站名称', align: 'center' },
{ field: 'CircuitMileage', title: '里程', width: 60, align: 'center' },
{ field: 'CircuitDirection', title: '方向', width: 60, align: 'center' },
{ field: 'PassengerStationCode', title: '所属车站编号', align: 'center', width: 120 },
{ field: 'PassengerStationName', title: '所属车站名称', align: 'center', width: 120 },
{ field: 'AreaName', title: '所属区域', align: 'center' },
{ field: 'CircuitRemark', title: '备注', align: 'center', width: 80 },
{ title: '停开', templet: StopCircuit, align: 'center', fixed: 'right', width: 60 },
{ title: '操作', templet: setOperateCircuit, align: 'center', fixed: 'right', width: 150 }
]], //开启分页
page: {
limit: 5,//指定每页显示的条数
limits: [5, 10, 15, 20, 25, 30, 35, 40, 45, 50],//每页条数的选择项
},
data: [],
})
//线路表监听单行点击事件(双击事件为:rowDouble)
layuiTable.on('row(tabCircuit)', function (obj) {
var data = obj.data;
//标中选中行样式
obj.tr.addClass('layui-table-click').siblings().removeClass('layui-table-click');
//选中行,勾选复选框
obj.tr.find("div.layui-unselect.layui-form-checkbox")[0].click();
var CircuitID = obj.data.CircuitID;
tabHighwaySection.reload({
url: "/BusinessManagement/CircuitManagement/selectHighWaySection",
where: {
CircuitID: CircuitID
},
page: {
curr: 1
}
});
});
//调用多条件查询方法
searchTabCircuit();
})
});
//多条件查询
function searchTabCircuit() {
var searchCircuitNameNum = $("#searchPlanCircuitCode").val();
if (searchCircuitNameNum == undefined) {
searchCircuitNameNum = "";
}
tabCircuit.reload({
url: "/BusinessManagement/CircuitManagement/SelectCircuit",
where: {
searchCircuitNameNum: searchCircuitNameNum
},
page: {
curr: 1
}
});
}
控制代码
在写控制器中的代码时要先判断你需要的字段是否都在一个表格中,如果在,那就可以直接写,如果不在,需要先添加一个类CircuitVo。在类名的后面可以继承主要表的所有字段,然后将主要表格中没有的字段在类中写上。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using TransportManagment.Models;
namespace TransportManagment.EntityClass
{
public class CircuitVo:SYS_Circuit
{
/// <summary>
/// 起点站编号
/// </summary>
public string StartStationCode { get; set; }
/// <summary>
/// 起点站名称
/// </summary>
public string StartStationName { get; set; }
/// <summary>
/// 终点站编号
/// </summary>
public string EndStationCode { get; set; }
/// <summary>
/// 终点站名称
/// </summary>
public string EndStationName { get; set; }
/// <summary>
/// 所属区域
/// </summary>
public string AreaName { get; set; }
/// <summary>
/// 所属车站编号
/// </summary>
public string PassengerStationCode { get; set; }
/// <summary>
/// 所属车站名称
/// </summary>
public string PassengerStationName { get; set; }
/// <summary>
/// 起点站ID
/// </summary>
public int StartStationID { get; set; }
/// <summary>
/// 终点站ID StationDetail
/// </summary>
public int EndStationID { get; set; }
public int StationDetailID { get; set; }
public int StartStationDetailID { get; set; }
}
}
完成CircuitVo之后,创建方法,string searchCircuitNameNum是用来接收数据库传过来的查询的条件(建议写完查询后在写条件查询)。由于这里查询的时候起点站和终点站都是在站点表中,直接查询的话不好直接同时查询出起点站和终点站。因此在查询线路数据之前先使用group…by 在站点明细表中根据线路ID(CircuitID)分组查询。group tbStationDetail by tbStationDetail.CircuitID into tbStation:表示对tbStationDetail按CircuitID进行分组,其结果命名为tbStation。然后查询,key属性:返回进行分组的关键字段的值;在这指的是tbStationDetail.CircuitID。上面提到CircuitStationTypeID等于1时,站点为起点站,等于2时,站点为终点站。起点站的ID等于分组之后的第一条数据的站点ID,终点站的ID为分组后根据站点类型ID进行倒序排序之后的第一条数据的站点ID。这样,就将每一条线路的起点站和终点站分隔开。
将起点站和终点站处理好了之后就可以进行数据的查询了。首先从上方查询出来的数据中查询,跟后连接线路表、区域表、车站表和站点表查询数据。需注意的是,连接站点表的时候要连接两次,分别是根据上面查出来的起点站ID和终点站ID来连表查询,最后插叙出自己需要的数据。可能是由于使用了分组的原因,每次查询出来的数据都会重复,因此在ToLost()前面加上Distnict()来去除重复的数据。至于排序呢,我预想的是所有线路状态为false和所有线路状态为true的分隔开来并且新增的数据在所在状态的第一条数据。因此,我先根据线路状态进行倒序排序,然后根据线路ID进行倒序排序。然后就是条件查询了,先判断view传过来的数据是否为空,如果不为空,再在查出来的所有的数据中进行条件查询。查出来的所有的数据中的线路名称(CircuitName)或者线路编号(CircuitNumber)的内容存在与传过来的条件相同的内容的所有数据。剩下的和我以前的文章:简单使用layui完成数据表格中的内容一致。
public ActionResult SelectCircuit(LayuiTablePage layuiTablePage, string searchCircuitNameNum)
{
var linqCircuit = from tbStationDetail in myModels.SYS_StationDetail
group tbStationDetail by tbStationDetail.CircuitID into tbStation
select new
{
CircuitID = tbStation.Key,
StartStationID = tbStation.FirstOrDefault().StationID,
EndStationID = tbStation.OrderByDescending(m => m.CircuitStationTypeID).FirstOrDefault().StationID,
};
List<CircuitVo> CircuitAll1 = (from tblinqCircuit in linqCircuit
join tbCircuit in myModels.SYS_Circuit on tblinqCircuit.CircuitID equals tbCircuit.CircuitID
join tbStartStation in myModels.SYS_Station on tblinqCircuit.StartStationID equals tbStartStation.StationID
join tbEndStation in myModels.SYS_Station on tblinqCircuit.EndStationID equals tbEndStation.StationID
join tbArea in myModels.SYS__Area on tbCircuit.AreaID equals tbArea.AreaID
join tbPassengerStation in myModels.SYS_PassengerStation on tbCircuit.PassengerStationID equals tbPassengerStation.PassengerStationID
select new CircuitVo
{
CircuitID = tbCircuit.CircuitID,
AreaID = tbCircuit.AreaID,
PassengerStationID = tbCircuit.PassengerStationID,
CircuitName = tbCircuit.CircuitName,
CircuitNumber = tbCircuit.CircuitNumber,
StartStationCode = tbStartStation.StationCode,
StartStationName = tbStartStation.StationName,
EndStationCode = tbEndStation.StationCode,
EndStationName = tbEndStation.StationName,
CircuitMileage = tbCircuit.CircuitMileage,
CircuitDirection = tbCircuit.CircuitDirection,
PassengerStationCode = tbPassengerStation.PassengerStationCode,
PassengerStationName = tbPassengerStation.PassengerStationName,
AreaName = tbArea.AreaName,
CircuitRemark = tbCircuit.CircuitRemark,
CircuitToVoidNo = tbCircuit.CircuitToVoidNo
}).Distinct().ToList();
//排序
List<CircuitVo> CircuitAll = CircuitAll1.OrderByDescending(m => m.CircuitToVoidNo).ThenByDescending(m => m.CircuitID).ToList();
if (!string.IsNullOrEmpty(searchCircuitNameNum))
{
CircuitAll = CircuitAll.Where(m => m.CircuitName.Contains(searchCircuitNameNum) || m.CircuitNumber.Contains(searchCircuitNameNum)).ToList();
}
int total = CircuitAll.Count();
List<CircuitVo> list = CircuitAll
.Skip(layuiTablePage.GetStartIndex())
.Take(layuiTablePage.limit)
.ToList();
LayuiTableData<CircuitVo> layuiTableData = new LayuiTableData<CircuitVo>
{
count = total,
data = list
};
return Json(layuiTableData, JsonRequestBehavior.AllowGet);
}