2015-05-05 3 views
1

Я создал инструмент поиска в MVC. Пользователь вводит строку searchTerm в поле поиска и выбирает параметры поиска из 2 списков выпадающего списка. Из первого списка пользователь выбирает «Fuzzy» или «Literal» для searchType, а из второго списка пользователь может выбрать конкретное поле для поиска, specField. Три значения строки передаются контроллеру после нажатия кнопки поиска.
Я пытаюсь написать оператор «if», который запрашивает модель DB Entity Framework на основе этих трех строковых значений, переданных в контроллер. Как написать запросы, которые используют эти значения? Это то, что у меня есть. Я знаю, что запросы не правильно:Как написать MVC Entity Framework выбрать запрос от контроллера с использованием переданных аргументов строки?

Public PartialViewResult _Search(string searchTerm, string specField, string searchType) 
{ 
     //This works to populate the table with the entire DB 
     _db = new IntegrationDBEntities(); 
     var request = (from r in _db.Requests 
        select r).ToList(); 

    //These two are not correct and I need help writing these 
    if (searchType == "Fuzzy" && searchTerm != "" && specField != "None") 
    { 
      request = (from r in _db.Requests 
          where r.(specField).Contains(searchTerm) 
          select r).ToList(); 
    } 
    if (searchType == "Literal" && searchTerm != "" && specField == "None") 
    { 
      request = (from r in _db.Requests 
         where r.Equals(searchTerm) 
         select r).ToList(); 
    } 
    ViewData.Model = request; 
    Return partialView(); 
} 

ответ

4

Я не 100% уверен, как выглядит объект Request, но я бы использовал PredicateBuilder. Вот пример того, как могла выглядеть ваша функция поиска.

IQueryable<Request> SearchRequests (string searchTerm, string specField, string searchType) 
{ 
    var predicate = PredicateBuilder.False<Request>(); 

    //These two are not correct and I need help writing these 
    if (searchType == "Fuzzy" && searchTerm != "" && specField != "None") 
    { 
     predicate = predicate.Or (r => r.(specField).Contains(searchTerm)); 
    } 
    if (searchType == "Literal" && searchTerm != "" && specField == "None") 
    { 
     predicate = predicate.Or (r => r.Equals(searchTerm)); 
    } 

    return new IntegrationDBEntities() 
        .Requests 
        .AsExpandable() 
        .Where(predicate); 
} 

Тогда ваш метод может выглядеть следующим образом:

Public PartialViewResult _Search(string searchTerm, string specField, string searchType) 
{ 
    ViewData.Model = SearchRequests(searchTerm, specField, searchType).ToList(); 
    Return partialView(); 
} 

UPDATE: Я добавил рабочий пример из LINQPad. Вам нужно будет немного изменить его, чтобы он работал для вас с EntityFramework.

void Main() 
{ 
    var results = SearchRequests("Fuzzy", "later").ToList(); 
    results.Dump(); 

    var results2 = SearchRequests("Literal", "Test me now").ToList(); 
    results2.Dump(); 
} 

// Define other methods and classes here 
public class Request 
{ 
    public int Id {get;set;} 
    public string SearchTerm {get;set;} 
} 

public IQueryable<Request> LoadData() 
{ 
    var list = new List<Request>(); 
    list.Add(new Request {Id = 1, SearchTerm = "Test me now"}); 
    list.Add(new Request {Id = 2, SearchTerm = "Test me later"}); 
    list.Add(new Request {Id = 3, SearchTerm = "Test me maybe"}); 
    list.Add(new Request {Id = 4, SearchTerm = "Test me now"}); 
    list.Add(new Request {Id = 5, SearchTerm = "Test me later or never"}); 
    list.Add(new Request {Id = 6, SearchTerm = "Test me maybe or today"}); 

    return list.AsQueryable(); 
} 

public IQueryable<Request> SearchRequests (string searchType, string searchTerm) 
{ 
    var data = LoadData(); 
    var predicate = PredicateBuilder.False<Request>(); 
    //These two are not correct and I need help writing these 
    if (searchType == "Fuzzy") 
    { 
     predicate = predicate.Or(r => r.SearchTerm.Contains(searchTerm)); 
    } 
    if (searchType == "Literal") 
    { 
     predicate = predicate.Or (r => r.SearchTerm.Equals(searchTerm)); 
    } 

    return data.Where(predicate); 
} 

public static class PredicateBuilder 
{ 
    public static Expression<Func<T, bool>> True<T>() { return f => true; } 
    public static Expression<Func<T, bool>> False<T>() { return f => false; } 

    public static Expression<Func<T, bool>> Or<T> (this Expression<Func<T, bool>> expr1, 
                 Expression<Func<T, bool>> expr2) 
    { 
     var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression>()); 
     return Expression.Lambda<Func<T, bool>> 
      (Expression.OrElse (expr1.Body, invokedExpr), expr1.Parameters); 
    } 

    public static Expression<Func<T, bool>> And<T> (this Expression<Func<T, bool>> expr1, 
                 Expression<Func<T, bool>> expr2) 
    { 
     var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression>()); 
     return Expression.Lambda<Func<T, bool>> 
      (Expression.AndAlso (expr1.Body, invokedExpr), expr1.Parameters); 
    } 
} 

Результаты по первому запросу:

Id SearchTerm 
2 Test me later 
5 Test me later or never 

Результаты для второго поиска:

Id SearchTerm 
1 Test me now 
4 Test me now 
+0

«predicate = predicate.Or (... «Части выдают мне ошибку. Также,« .AsExpandable() »также. – antman1p

+0

@ antman1p Я обновил ответ с помощью рабочего примера LinqPad. AsExpandable() необходим для EntityFramework, но поскольку я не использую EntityFramework в примере , Я не могу подтвердить эту часть. PredicateBuilder тверд, на мой взгляд. Дайте мне знать, как это происходит. – CrnaStena

+0

@CmaStena Я просто прочитал, что мне нужно будет скачать LinqKit.dll – antman1p

0

Надеется, что это работает без ошибок:

ParameterExpression pe = Expression.Parameter(typeof(Request), "Request"); 
Expression property = Expression.Property(pe, specField); 
Expression predicate = null; 
Expression srch = Expression.Constant(searchTerm, typeof(string)); 
if(searchType == "Fuzzy") 
{ 
    MethodInfo contains = typeof(string).GetMethod("Contains", new Type[] { typeof(string) }); 
    predicate = Expression.Call(property, contains, srch); 
} 
else 
{ 
    predicate = Expression.Equal(property, srch); 
} 

MethodCallExpression where = Expression.Call(
    typeof(Queryable), 
    "Where", 
    new Type[] { _db.Requests.ElementType }, 
    _db.Requests.Expression, 
    Expression.Lambda<Func<Request, bool>>(predicate, new ParameterExpression[] { pe })); 

IQueryable<Request> result = _db.Requests.Provider.CreateQuery<Request>(where); 

var list = result.ToList(); 

Позволь мне знать, если у вас есть какие-либо проблемы

+0

Почему вы полностью квалифицированное все ваши типы? – Yuck

+0

На всякий случай. Но это делает его менее читаемым. –

+1

Я получаю сообщение об ошибке «Best Overloaded method ....» для: Epression containsFoo = Expression.Call (свойство, содержит, searchTerm); – antman1p

 Смежные вопросы

  • Нет связанных вопросов^_^