2015-07-17 4 views
0

Я новичок в EF. У меня есть таблица со списком проектов. Я нашел запрос в своем программном обеспечении, который находит все проекты.Как параметризовать запрос в Entity Framework?

public Project[] FindAll() 
{ 
    var projects = new List<Project>(); 
    using (var db = new ProjetDbConext()) 
    { 
     var qProjects = from project in db.ProjectSet 
      where project.CreateDateTime != null 
      select project; 
     projects = qProjects.ToList(); 
    } 
    return projects.ToArray(); 
} 

Это кажется прекрасным, но я не уверен, как его параметрировать. Мне нужно это, потому что я реализую функцию поиска, пытаясь использовать некоторую логику запроса из EF.

Это берет Список кортежей. Каждый кортеж в основном имеет атрибут и список условий поиска.

например. Tuple (FirstName, {Prasaanth, Bill}; Tuple (LastName, {Neelakandan, Gates};

Это означает, что мне нужно написать запрос выбора, где я ищу проекты, где FirstName - Prasaanth или Bill. Если в списке есть только один .. термин

например Кортеж (компания, {Microsoft}, тогда я должен искать только одно, когда условие в мой запрос

public Project[] LoadSearchProjects(List<System.Tuple<string, List<string>>> searchTerms) 
     { 
      var projects = new List<Project>(); 

      using (var db = new ProjetDbConext()) 
      { 
       foreach (System.Tuple<string, List<string>> pair in searchTerms) 
       { 

        string attribute = pair.Item1; 
        List<string> terms = pair.Item2; 

         /// logic here 
       } 
      } 
      return projects.ToArray(); 

     } 

я всегда могу написать, если условие, когда я делаю:

.
if(attribute.equals("FirstName"){ 

// query project.FirstName in the where conditon 


} 

Но у меня слишком много атрибутов для поиска.

Я знаю, что ADO.NET способ сделать это:

mycommands = new SqlCommand(" select projects from from Persons where '"+attibute+"' = some search terms ... 

Я не знаю, как сделать что-то подобное в моей EF запросе.

1) Есть ли способ, которым EF позволяет мне выполнять поиск по динамическим атрибутам? или параметризировать, используя атрибут «+» + «»?

2) Есть ли лучшая структура данных, которую я мог бы использовать для упрощения моей структуры вместо использования List<Tuple<string, List<string>>?

3) Я рекомендовал использовать сторонний LINQKit или динамический linq, но не уверен, как интегрировать это в EF-запрос.

Приношу извинения, если многое из этого звучит, как код колледжа. Пожалуйста, дайте мне знать, если вам нужна дополнительная информация.

С уважением, Prasaanth

UPDATE: Метод работы в соответствии с ответом Andriy в. Мой вопрос здесь в том, что это не работает, если какая-либо конкретная запись в моей базе данных говорит, что имя Null.

private static Expression<Func<TEntity, bool>> BuildStringFilter<TEntity, TProp>(
      Tuple<string, List<string>> filter) 
     { 
      // entity is the Project table 
      var entity = Expression.Parameter(typeof (TEntity)); 
      var prop = Expression.Property(entity, filter.Item1); 

      //check if contains returns true 

      var body = filter.Item2 
       .Select(v => Expression.Equal(Expression.Call(prop, 
        typeof (String).GetMethod("Contains"), 
        new Expression[] { Expression.Constant(v) }), Expression.Constant(true))) 
       .Aggregate(Expression.Or); 



      var result = (Expression<Func<TEntity, bool>>) Expression.Lambda(body, entity); 
      return result; 
     } 

В любом случае, я могу изменить выражение так, что содержит метод:

проп, TypeOf (String) .GetMethod ("Содержит"), новое выражение [] {Expression.Constant (v)

работает, если значение атрибута (prop) равно null?

+0

Обратите внимание на библиотеку [System.Linq.Dynamic] (https://www.nuget.org/packages/System.Linq.Dynamic/) –

ответ

2

Вы можете создать выражение фильтра, используя фрагмент кода:

public static Expression<Func<TEntity, bool>> BuildFilter<TEntity, TProp>(
    KeyValuePair<string, IEnumerable<TProp>> filter) 
{ 
    var entity = Expression.Parameter(typeof(TEntity)); 
    var prop = Expression.Property(entity, filter.Key); 

    var body = filter.Value 
     .Select(v => Expression.Equal(prop, Expression.Constant(v))) 
     .Aggregate((curr, next) => Expression.Or(curr, next)); 

    var result = (Expression<Func<TEntity, bool>>)Expression.Lambda(body, entity); 
    return result; 
} 

И назовите это так:

var filter = new KeyValuePair<string, IEnumerable<string>> (
    "FirstName", 
    new [] {"Alice", "Bob"} 
); 

var predicate = BuildFilter<Item, string>(filter); 
var result = ctx.Items.Where(predicate); 

Также см. How to: Use Expression Trees to Build Dynamic Queries.

+0

hi .. является ctx экземпляром ProjetDbContext() ?? Когда я называю это, он не может найти символ Item? –

+0

Элемент в вызове BuildFilter? –

+0

Ctx - это экземпляр DbContext, а Items - это DbSet. Вы можете использовать db и ProjectSet вместо этого в вашем случае. –

0

Я spitballing здесь, но я думаю, что что-то подобное было бы проще:

public Project[] Find(Expression<Func<Project, bool> filter = null) 
{  
    using (var db = new ProjetDbConext()) 
    { 
     var query = db.ProjectSet.Where(p => p.CreateDateTime != null); 

     if(filter != null) 
      query = query.Where(filter); 

     return query.ToArray(); 
    } 
} 

использовать его как:

var projects = repo.Find(p => p.id > 100); 
+0

Это не позволяет мне предоставлять атрибут для поиска на лету. например, id в случае примера u, предоставленного –

+0

, что вы подразумеваете под «на лету»? он позволяет искать проекты на основе произвольных предикатов. – kai

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