Как реализовать функцию поиска в C # / ASP.NET MVC - PullRequest
11 голосов
/ 29 августа 2011

Я занимаюсь разработкой приложения ASP.NET MVC 3 с использованием C # и Razor.

У меня есть форма поиска, которая выглядит следующим образом: searchform

Форма поиска работает следующим образом:

  1. Пользователь выбирает, какое свойство он хочетдля поиска.
  2. Пользователь выбирает, как он хочет сопоставить строку поиска (например, содержит, начинается с, заканчивается на, равно и т. д.).
  3. Пользователь вводит условие поиска и щелкаетПоиск.

Выборы в первом раскрывающемся списке связаны непосредственно со свойством в моем классе модели ADO.NET Entity Framework (и, следовательно, непосредственно со столбцом таблицы).

Потребности пользователейвозможность явно выбирать, какое свойство и какой метод сопоставления при поиске, например, пользователь будет явно искать все совпадения с номером процесса, равным «132».

Мой первый подход заключался в использовании динамического linq для построения Whereпункт из критериев поиска ( см. мой оригинальный вопрос ).Однако я начинаю думать, что это не лучший способ сделать это.

Я также надеюсь на решение, которое не требует от меня жесткого кода результата для каждого свойства + критерий соответствиякомбинация.

Любые предложения о том, как я должен реализовать этот поиск?Не нужно использовать мою текущую форму поиска, полностью открытую для любых других идей, которые соответствуют требованиям.

Ответы [ 7 ]

12 голосов
/ 29 августа 2011

Вы рассматривали возможность использования Lucene.NET для этого проекта?учитывая характер ваших поисков, было бы очень просто создать его с помощью Lucene, поскольку он позволяет комбинировать фильтры по разным столбцам так же, как ваши требования

4 голосов
/ 16 сентября 2011

Вы можете построить дерево выражений для предиката where, используя код.Например,

public static IQueryable<T> DynamicWhere<T>(this IQueryable<T> 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<Func<T, bool>>(condition, pe);
    return src.Where(predicate);
}

Используйте его как Orders.DynamicWhere(searchBy, searchValue).Вы можете добавить еще один параметр, чтобы принять оператор, такой как Equals, Greater Than и т. Д. Для завершения функции.

Для получения дополнительной информации см. Эти ссылки:

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

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

Также проверьте список методов класса Expression , чтобы получить представление.

0 голосов
/ 01 апреля 2016

создайте метод и вызовите его на демонстрации нажатия кнопки ниже

публичный список gettaskssdata (int c, int userid, строка a, строка StartDate, строка EndDate, строка ProjectID, строка statusid) {

        List<tbltask> tbtask = new List<tbltask>();


        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;

    }
0 голосов
/ 21 сентября 2011

Первый источник комбинированных данных может иметь значение myEntityObject.GetType (). GetProperties (), второе в списке отображаемых Funcs<string, string, bool>, например:

public class ComboPredicate
{
    public Func<string, string, bool> Func {get; set;}
    public string Name {get; set; }
}

Позже, когда вызагрузить форму:

comboProperty.Datasource = myEntityObject.GetType().GetProperties()
comboOperation.Datasource = new List<Predicate>
    {
        {
            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));
0 голосов
/ 21 сентября 2011

Не уверен, что вы используете 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)
0 голосов
/ 19 сентября 2011

Мы начали разрешать похожие запросы к нашей модели Entity Framework, используя динамические запросы linq. Однако наши попытки обобщить генерацию запросов привели к снижению производительности из-за того, что EF был сбит с толку полученными сложными выражениями, поэтому в итоге был получен ужасный SQL.

Мы прибегли к Entity SQL .

0 голосов
/ 16 сентября 2011

Вы можете использовать Dynamic Linq, и вы можете создать клаузол Where с утилитарным классом, подобным следующему:

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, и поместить их вГде оператор Dynamic Linq.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...