在 ASP.NET MVC (C#) 和 LINQ-to-SQL 中的视图上实现 SQL 表显示的过滤器?
-
20-08-2019 - |
题
后续行动来自 这个问题, ,我更改了控制器和路由,以便现在排序值由 ?sort= 分配,但是我还希望实现用户根据一组选定的值过滤表的功能:
技术员:技术 1、技术 2、技术 3 等类别 :类别 1、类别 2、类别 3 等优先事项 :优先级 1、优先级 2、优先级 3 等
我目前只使用一张表,因此获取要过滤的可用类别列表的最简单方法是从表中选择不同的类别值。它们都是通过 HTML 输入的,因此我可以控制输入的内容。我还不想将它们全部拆分到不同的表中,我现在正在尝试用一张表做尽可能多的事情,但如果这是破坏单表模型的场景,那么很好,我可以调整。
为了澄清用例,最好显示相关视图的快速屏幕截图:
http://images.robburke.ie/stackoverflow/491563.png
单击查看全尺寸。
我想实现一个系统,用户可以通过该系统过滤“优先级”,仅显示优先级为“调查”的问题。
我正在寻找有关如何在前端和后端实现此功能的建议。我试图找到一个可以对数据表执行类似操作的网站,但我无法想到其中一个,尽管我确信这是一项之前已经实现了一百次的功能!
谁能推荐一个好方法来做到这一点?
解决方案
服务器层
让我们从一些伪代码开始。
public ActionResult Open(string sort, string technician,
string category, string priority)
{
// generate query
// filter stuff
// order/sort stuff
}
在这里,正确执行操作顺序非常重要。某些 IQueryable 提供程序(我正在看着你,实体框架) 如果排序出现在过滤之前,将默默地忽略排序。因此,首先生成一个无序、未过滤的查询,就像您的上一个问题一样,然后附加过滤,最后附加顺序。
请注意,我已经为每个可能的过滤器案例添加了一个参数到您的操作中。这是一种方法。另一种方法是允许对任何内容进行过滤,通过迭代查询字符串参数(在请求内部)将任何不称为“排序”的内容视为潜在的过滤器。您应该选择最适合您的应用程序的。
现在,您如何实际实现过滤?马克展示的是一种方式。如果您只想过滤某些情况,那么这种方法非常有效。显然,我会将其放在辅助方法中,而不是放在操作本身中。您很可能需要重用此帮助程序和其他操作。但是,如果您打算对比您希望在单个方法中详细说明的行数更多的行提供过滤,则另一种方法是使用 Microsoft Dynamic LINQ 库,您可以从 CodePlex 获取该库。这允许您使用字符串而不是 lambda 表达式构建 LINQ .Where。
浏览器层
现在您的应用程序可以处理此问题,您需要一种创建链接的方法,如下所示:
http://example.com/Issue/Open?sort=ID&priority=Investigative
例如,如果您有一个过滤选项菜单,则每个菜单项将对应于具有不同查询字符串参数的链接。
这有点棘手,因为您可能希望在添加新查询字符串参数时保留现有的查询字符串参数。例如,如果用户已按 ID 对未解决的问题进行排序,并选择仅过滤调查优先级问题,您仍然希望保留该排序。因此,菜单中的所有链接都需要包含当前显示页面的查询字符串参数以及菜单项本身的查询字符串参数。
因此,我们在执行此操作时采取的一般方法是,对于“过滤菜单”中的每个项目(或您的建筑物的任何链接):
- 创建查询字符串参数的 RouteValueDictionary
- 将传递到当前视图的所有查询字符串参数添加到字典中。
- 为当前菜单项添加附加查询字符串参数。
- 使用 Html.RouteLink 和我们构建的字典生成最终 URL。
其他提示
我不完全理解的用例 - 但你可以通过IQueryable<T>
轻松添加滤镜:
var query = /* your primary query */
if(!string.IsNullOrEmpty(name)) {
query = query.Where(row => row.Name == name);
}
if(activeOnly) {
query = query.Where(row => row.IsActive);
}
等
可以通过手动构建Expression
de做更复杂的事情,但上述具有容易调试的优点,和编译器检查(编译器将确保有合适的IsActive
财产等)