如何在C#/ ASP.NET MVC中实现搜索function

我正在使用C#和Razor开发ASP.NET MVC 3应用程序。

我有一个看起来像这样的搜索表单: searchform

搜索表单以下列方式工作:

  1. 用户选择他们想要搜索的属性。
  2. 用户选择他们想要匹配搜索字符串的方式(例如包含,开头,结尾,等等)。
  3. 用户输入搜索词并单击“搜索”。

第一个下拉列表中的选择直接与我的ADO.NET Entity Framework模型类中的属性相关(因此直接与表列相关)。

用户需要能够在搜索时明确选择哪个属性和哪个匹配方法,例如用户将明确搜索等于’132’的进程号的所有匹配。

我的第一种方法是使用动态linq从搜索条件构造Where子句( 参见我原来的问题 )。 但是我开始认为这不是最好的方法。

我也希望有一个解决方案,不要求我对每个属性+匹配标准组合的结果进行硬编码。

有关如何实施此搜索的任何建议? 它不必使用我当前的搜索表单,完全接受符合要求的任何其他想法。

您可以使用代码为谓词构建表达式树。 例如,

public static IQueryable DynamicWhere(this IQueryable src, string propertyName, string value) { var pe = Expression.Parameter(typeof(T), "t"); var left = Expression.Property(pe, typeof(T).GetProperty(propertyName)); var right = Expression.Constant(value); // Illustrated a equality condition but you can put a switch based on some parameter // to have different operators var condition = Expression.Equal(left, right); var predicate = Expression.Lambda>(condition, pe); return src.Where(predicate); } 

将它用作Orders.DynamicWhere(searchBy, searchValue) 。 您可以添加一个参数来接受运算符,例如Equals,Greater Than等,以完成该function。

有关详细信息,请参阅以下链接

http://msdn.microsoft.com/en-us/library/bb882637.aspx

http://msdn.microsoft.com/en-us/library/bb397951.aspx

还要检查Expression类上的方法列表以获得想法。

您是否考虑过将Lucene.NET用于此项目? 考虑到搜索的性质,使用Lucene进行构建非常简单,因为它允许您根据需要组合不同列上的filter

您可以使用Dynamic Linq,您可以使用如下的实用程序类创建Where clausole:

 public class Criteria { StringBuilder sb = new StringBuilder(); bool first = true; public void And(string property, string dbOperator, string value) { if (first) { sb.Append(" ").Append(property).Append(" "); sb.Append(" ").Append(dbOperator).Append(" "); sb.Append(" ").Append(value).Append(" "); first = false; } else { sb.Append(" && ").Append(property).Append(" "); sb.Append(" ").Append(dbOperator).Append(" "); sb.Append(" ").Append(value).Append(" "); } } public void Or(string property, string dbOperator, string value) { if (first) { sb.Append(" ").Append(property).Append(" "); sb.Append(" ").Append(dbOperator).Append(" "); sb.Append(" ").Append(value).Append(" "); first = false; } else { sb.Append(" || ").Append(property).Append(" "); sb.Append(" ").Append(dbOperator).Append(" "); sb.Append(" ").Append(value).Append(" "); } } public string ToString() { return sb.ToString(); } } 

因此,您可以使用Or或And方法构建具有许多属性的Criteria,并将其放在Dynamic Linq的Where运算符中。

我们开始使用动态linq查询来解析针对我们的Entity Framework模型的类似查询。 但是,由于EF被生成的复杂表达式混淆,我们尝试概括查询生成导致性能不佳,因此最终产生了可怕的SQL。

我们使用了Entity SQL 。

不确定您是否使用MS SQL。 似乎SQL可以为您完成大部分工作,您可以构建动态查询。 显然select / from语句需要工作,但你可以从where子句中获得想法。

 DECLARE @SEARCHTYPE VARCHAR(20) DECLARE @SEARCHTERM VARCHAR(100) SELECT [FIELDS] FROM [TABLE] WHERE (@SEARCHTYPE = 'BEGINSWITH' AND [FIELD] LIKE @SEARCHTERM + '%') OR (@SEARCHTYPE = 'ENDSWITH' AND [FIELD] LIKE '%' + @SEARCHTERM) OR (@SEARCHTYPE = 'EQUALS' AND [FIELD] = @SEARCHTERM) 

您可以将第一个组合数据源设置为myEntityObject.GetType()。GetProperties(),第二个显示可显示的Funcs ,如下所示:

 public class ComboPredicate { public Func Func {get; set;} public string Name {get; set; } } 

稍后,当您加载表单时:

 comboProperty.Datasource = myEntityObject.GetType().GetProperties() comboOperation.Datasource = new List { { Name = "Contains", Predicate = (s1, s2) => s1 != null && s1.Contains(s2), }, { Name = "Equals", Predicate = (s1, s2) => string.Compare(s1, s2) == 0, }, //... } 

之后,当您想要选择实体时:

 var propertyInfo = (PropertyInfo)comboProperty.SelectedValue; var predicate = ((ComboPredicate)comboOperation.SelectedValue).Predicate; var filteredObjects = objects.Where(o => predicate(propertyInfo.GetValue(o, null).ToString(), textBoxValue.Text)); 

创建方法并在下面的按钮单击演示中调用它

public List gettaskssdata(int c,int userid,string a,string StartDate,string EndDate,string ProjectID,string statusid){

  List tbtask = new List(); var selectproject = entity.tbluserprojects.Where(x => x.user_id == userid).Select(x => x.Projectid); if (statusid != "" && ProjectID != "" && a != "" && StartDate != "" && EndDate != "") { int pid = Convert.ToInt32(ProjectID); int sid = Convert.ToInt32(statusid); DateTime sdate = Convert.ToDateTime(StartDate).Date; DateTime edate = Convert.ToDateTime(EndDate).Date; tbtask = entity.tbltasks.Include(x => x.tblproject).Include(x => x.tbUser).Where(x => selectproject.Contains(x.ProjectId) && (x.tblproject.company_id == c) && (x.tblproject.ProjectId == pid) && (x.tblstatu.StatusId == sid) && (x.TaskName.Contains(a) || x.tbUser.User_name.Contains(a)) && (x.StartDate >= sdate && x.EndDate <= edate)).OrderByDescending(x => x.ProjectId).ToList(); } else if (statusid == "" && ProjectID != "" && a != "" && StartDate != "" && EndDate != "") { int pid = Convert.ToInt32(ProjectID); DateTime sdate = Convert.ToDateTime(StartDate).Date; DateTime edate = Convert.ToDateTime(EndDate).Date; tbtask = entity.tbltasks.Include(x => x.tblproject).Include(x => x.tbUser).Where(x => selectproject.Contains(x.ProjectId) && (x.tblproject.company_id == c) && (x.tblproject.ProjectId == pid) && (x.TaskName.Contains(a) || x.tbUser.User_name.Contains(a)) && (x.StartDate >= sdate && x.EndDate <= edate)).OrderByDescending(x => x.ProjectId).ToList(); } else if (ProjectID == "" && statusid != "" && a != "" && StartDate != "" && EndDate != "") { int sid = Convert.ToInt32(statusid); DateTime sdate = Convert.ToDateTime(StartDate).Date; DateTime edate = Convert.ToDateTime(EndDate).Date; tbtask = entity.tbltasks.Include(x => x.tblproject).Include(x => x.tbUser).Where(x => selectproject.Contains(x.ProjectId) && (x.tblproject.company_id == c) && (x.tblstatu.StatusId == sid) && (x.TaskName.Contains(a) || x.tbUser.User_name.Contains(a)) && (x.StartDate >= sdate && x.EndDate <= edate)).OrderByDescending(x => x.ProjectId).ToList(); } else if(ProjectID!="" && StartDate == "" && EndDate == "" && statusid == "" && a == "") { int pid = Convert.ToInt32(ProjectID); tbtask = entity.tbltasks.Include(x => x.tblproject).Include(x => x.tbUser).Where(x => selectproject.Contains(x.ProjectId) && (x.tblproject.company_id == c) && (x.tblproject.ProjectId == pid)).OrderByDescending(x => x.ProjectId).ToList(); } else if(statusid!="" && ProjectID=="" && StartDate == "" && EndDate == "" && a == "") { int sid = Convert.ToInt32(statusid); tbtask = entity.tbltasks.Include(x => x.tblproject).Include(x => x.tbUser).Where(x => selectproject.Contains(x.ProjectId) && (x.tblproject.company_id == c) && (x.tblstatu.StatusId == sid) ).OrderByDescending(x => x.ProjectId).ToList(); } else if (a == "" && StartDate != "" && EndDate != "" && ProjectID != "") { int pid = Convert.ToInt32(ProjectID); DateTime sdate = Convert.ToDateTime(StartDate).Date; DateTime edate = Convert.ToDateTime(EndDate).Date; tbtask = entity.tbltasks.Include(x => x.tblproject).Include(x => x.tbUser).Where(x => selectproject.Contains(x.ProjectId) && (x.tblproject.ProjectId == pid) && (x.StartDate >= sdate && x.EndDate <= edate)).OrderByDescending(x => x.ProjectId).ToList(); } else if (StartDate == "" && EndDate == "" && statusid != "" && ProjectID != "" && a != "") { int pid = Convert.ToInt32(ProjectID); int sid = Convert.ToInt32(statusid); tbtask = entity.tbltasks.Include(x => x.tblproject).Include(x => x.tbUser).Where(x => selectproject.Contains(x.ProjectId) && (x.tblproject.company_id == c) && (x.tblproject.ProjectId == pid) && (x.tblstatu.StatusId == sid) && (x.TaskName.Contains(a) || x.tbUser.User_name.Contains(a))).OrderByDescending(x => x.ProjectId).ToList(); } else if (a == "" && StartDate == "" && EndDate == "" && ProjectID != "" && statusid != "") { int pid = Convert.ToInt32(ProjectID); int sid = Convert.ToInt32(statusid); tbtask = entity.tbltasks.Include(x => x.tblproject).Include(x => x.tbUser).Include(x => x.tblstatu).Where(x => selectproject.Contains(x.ProjectId) && x.tblproject.company_id == c && x.tblproject.ProjectId == pid && x.tblstatu.StatusId == sid).OrderByDescending(x => x.ProjectId).ToList(); } else if (a != "" && StartDate == "" && EndDate == "" && ProjectID == "" && statusid == "") { tbtask = entity.tbltasks.Include(x => x.tblproject).Include(x => x.tbUser).Where(x => selectproject.Contains(x.ProjectId) && (x.tblproject.company_id == c) && (x.TaskName.Contains(a) || x.tbUser.User_name.Contains(a))).OrderByDescending(x => x.ProjectId).ToList(); } else if (a != "" && ProjectID != "" && StartDate == "" && EndDate == "" && statusid == "") { int pid = Convert.ToInt32(ProjectID); tbtask = entity.tbltasks.Include(x => x.tblproject).Include(x => x.tbUser).Where(x => selectproject.Contains(x.ProjectId) && (x.tblproject.company_id == c) && (x.tblproject.ProjectId == pid) && (x.TaskName.Contains(a) || x.tbUser.User_name.Contains(a))).OrderByDescending(x => x.ProjectId).ToList(); } else if (a != "" && StartDate != "" && EndDate != "" && ProjectID == "" && statusid == "") { DateTime sdate = Convert.ToDateTime(StartDate).Date; DateTime edate = Convert.ToDateTime(EndDate).Date; tbtask = entity.tbltasks.Include(x => x.tblproject).Include(x => x.tbUser).Where(x => selectproject.Contains(x.ProjectId) && (x.tblproject.company_id == c) && (x.TaskName.Contains(a) || x.tbUser.User_name.Contains(a)) && (x.StartDate >= sdate && x.EndDate <= edate)).OrderByDescending(x => x.ProjectId).ToList(); } else { tbtask = entity.tbltasks.Include(x => x.tblproject).Include(x => x.tbUser).Where(x => selectproject.Contains(x.ProjectId) && x.tblproject.company_id == c).OrderByDescending(x => x.ProjectId).ToList(); } return tbtask; }