【问题标题】:Perform wildcard search of all (displayed) model fields in MVC?对 MVC 中的所有(显示的)模型字段执行通配符搜索?
【发布时间】:2015-06-09 00:07:17
【问题描述】:

我有一个 MVC5 视图,我在其中使用 Grid.MVC 组件 (https://gridmvc.codeplex.com/)。这使我可以轻松地显示来自我的 Oracle 数据库的数据,并且具有用于对每个数据列进行排序/过滤的开箱即用功能。我现在要实现的是跨网格中所有字段的通配符搜索。例如,如果我搜索数字“2”,我想返回所有包含“2”的记录,无论它们是字符串、十进制还是日期时间。

此网格上的过滤功能通过修改 URL (http://homeURL/?grid-filter=Location.DEPT__1__accounting) 部分执行过滤(针对单个列),例如 1 是 Equals,2 是 Contains,3 是 StartsWith,4 是 @ 987654326@ 然后在接下来的 2 个下划线之后是搜索条件。

我首先认为我正在走正确的道路,使用 JavaScript 修改为所需的 URL,方法是使用 CONTAINS 将所有字段与搜索条件进行菊花链。然后我注意到像 [Cost] 和 DateTime (Oracle DB) 像 [Acquired_Date] 这样的 decimal 字段的标准设置为 Equals, Greater Than, and Less Than,所以我尝试了:

$('#SearchIcon').on("click", function (e) {
            window.location = window.location.href.substr(0, window.location.href.indexOf('?'));
            window.location = "?grid-filter=FIELD1__2__" + document.getElementById("Search").value +
                              "&grid-filter=FIELD2__2__" + document.getElementById("Search").value +
                              "&grid-filter=COST__1__" + document.getElementById("Search").value +
                              // etc. -- ALL FIELDS
                              "&grid-filter=NOTE__2__" + document.getElementById("Search").value;
        });

这在技术上起作用,但 [&] 正在搜索在每个字段中具有相应搜索条件的记录。我需要的是类似的东西,但带有 OR [||] 条件----不幸的是,网格组件不包含这种形式的功能。

然后我想将搜索条件传递给控制器​​操作并通过 multi-WHERE 子句使用它,并仅将适合过滤器的记录返回到我的视图:

public ActionResult SearchAssets(string searchCriteria)
        { 
            fillPagingIntervalList();
            var assetSearchResults = db.ENTITY_COLLECTION.Where(m => m.ID.ToString() == searchCriteria ||
            m.Model.ToString() == searchCriteria ||
            m.COST.ToString() == searchCriteria ||
            // etc. -- ALL FIELDS
            ).FirstOrDefault();
            var assetCount = db.ENTITY_COLLECTION.ToList().Count();
            return View(assetSearchResults);
        }

这导致 WHERE 子句出现错误,说明查看 Inner Exception 了解详细信息 -- ORA-12704: character set mismatch MVC。然后,我将多个条件减少到只有 2 个要搜索的字段以进行调试:

var assetSearchResults = db.ENTITY_COLLECTION.Where(m => m.ID.ToString() == searchCriteria ||
            m.Model.ToString() == searchCriteria).FirstOrDefault();

导致: EntityCommandExecutionException 未被用户代码处理。

An exception of type 'System.Data.Entity.Core.EntityCommandExecutionException' occurred in EntityFramework.dll but was not handled in user code

Additional information: An error occurred while executing the command definition. See the inner exception for details.

Inner Exception: ORA-00932: inconsistent datatypes: expected - got NCLOB

有人知道如何获得我想要的工作吗?我也尝试了.Where(...con1...).Where(...con2...).Where(...etc...),但结果相同。我认为跨所有领域的通配符搜索很难实现,但事实证明这比我预期的要大。

【问题讨论】:

  • Oracle 的实施看起来很糟糕。您的查询看起来可以在 SQL Server 上正常运行。

标签: asp.net-mvc oracle linq entity-framework asp.net-mvc-5


【解决方案1】:

这会很慢,但试试这个,它会将整个集合加载到对象中,并让 LINQ 在客户端进行过滤:

public ActionResult SearchAssets(string searchCriteria)
    { 
        fillPagingIntervalList();
        var assetSearchResults = db.ENTITY_COLLECTION.ToList().Where(m => m.ID.ToString() == searchCriteria ||
        m.Model.ToString() == searchCriteria ||
        m.COST.ToString() == searchCriteria ||
        // etc. -- ALL FIELDS
        ).FirstOrDefault();
        var assetCount = db.ENTITY_COLLECTION.ToList().Count();
        return View(assetSearchResults);
    }

你可以试试这样的:

public ActionResult SearchAssets(string searchCriteria)
    { 
        fillPagingIntervalList();
        var assetSearchResults = db.ENTITY_COLLECTION.Where(m => m.ID.ToString() == searchCriteria)
        .Union(db.ENTITY_COLLECTION.Where(m =>m.Model.ToString()==searchCriteria))
        .Union(db.ENTITY_COLLECTION.Where(m =>m.COST.ToString() == searchCriteria))
        // etc. -- ALL FIELDS
        var assetCount = db.ENTITY_COLLECTION.ToList().Count();
        return View(assetSearchResults);
    }

不过,我最终还是建议研究一下谓词构建器之类的东西。无论如何,这似乎是你正在做的事情。

【讨论】:

  • 啊,.Union 是我最初在 Controller 中尝试寻找的东西!我现在已经更改了它,但是有一个问题:The model item passed into the dictionary is of type 'System.Data.Entity.Infrastructure.DbQuery1[Project.DAL.ENTITY_COLLECTION]',但是这本字典需要一个类型为“System.Collections.Generic.List1[Project.DAL.ENTITY_COLLECTION]'.我的视图”的模型项将过滤后的集合返回到期望列表:@model List<Project.DAL.ENTITY_COLLECTION>。当我在最后一个.Union() 之后添加.ToList() 时,我得到expected - got NCLOB 的先前错误...?
  • 当我尝试较慢的.ToList().Where(... || .... ||.... etc.) 方法时,我收到An exception of type 'System.NullReferenceException' occurred in InventoryTracker.dll but was not handled in user code Additional information:Object reference not set to an instance of an object.,我认为这是由于我的几个字段包含空值。
  • 然后我尝试检查每个null(例如)m.MODEL_ID != null && m.MODEL_ID.ToString() == searchCriteria ||,但现在收到:An exception of type 'System.InvalidOperationException' occurred in System.Web.Mvc.dll but was not handled in user code. Additional information: The model item passed into the dictionary is of type 'System.Data.Entity.DynamicProxies.ENTITY_COLLECTION_E8B1D181BBB88B9C34D87212BA68486F709960DF8F42CAA9028631D5037F93F5', but this dictionary requires a model item of type 'System.Collections.Generic.List1[Project.DAL.ENTITY_COLLECTION]'.
  • 最后一个错误似乎您需要在将 .ToList() 传递到视图之前调用它。
  • 最后一个关于DynamicProxies?当我已经拥有db.ENTITY_COLLECTION.ToList().Where(..... || ..... || .... etc).FirstOrDefault(); 时,为什么还要再次调用.ToList()?就像我转到最后一行代码 return View(assetSearchResults); 并尝试添加 .ToList() 时一样,智能感知显示唯一的 To 选项为 ToString()
猜你喜欢
  • 1970-01-01
  • 2022-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-03
相关资源
最近更新 更多