Проблемы с LINQ WhereClause - PullRequest
       23

Проблемы с LINQ WhereClause

2 голосов
/ 07 января 2011

Большое спасибо Леппи: В настоящее время я получил

Expression<Func<vwMailMerge,bool>> whereClause= null;
List<vwMailMerge> mailMergeItems = null;

int personType = mailMergeSettings.PersonType.ToInteger();
if (personType > 0)
{
    whereClause = this.MailMergeWhereClause(whereClause, f => f.MemberTypeId == personType);
}
if (mailMergeSettings.PersonIds != null)
{
    var personIds = mailMergeSettings.PersonIds.ToGuidArray();
    if (personIds != null && personIds.Length > 0)
    {
        var personList = personIds.ToList();
        whereClause = this.MailMergeWhereClause(whereClause, f => personList.Contains(f.UserId));
    }
}

mailMergeItems = this.ObjectContext.vwMailMerges.Where(whereClause).ToList();
private Expression<Func<vwMailMerge, bool>> MailMergeWhereClause(params Expression<Func<vwMailMerge, bool>>[] wheres)
{
    if (wheres.Length == 0)
    {
        return x => true;
    }
    Expression result;   
    if (wheres[0] == null)
    {
        result = wheres[1].Body;
        return Expression.Lambda<Func<vwMailMerge, bool>>(result, wheres[1].Parameters);
    }
    else
    {
        result = wheres[0].Body;
        for (int i = 1; i < wheres.Length; i++)
        {
            result = Expression.And(result, wheres[i].Body);
        }
        return Expression.Lambda<Func<vwMailMerge, bool>>(result, wheres[0].Parameters);
        }     
    }
}

Когда он достигает «mailMergeItems =», он сбрасывает и выдает ошибку: «Параметр 'f' не был связан в указанном выражении запроса LINQ to Entities."

Я заметил, что при проверке только для людей, или только для membertypeId, он работает должным образом ... но в сочетании 2-й дает ошибку на "f =>", я думаю.

Ответы [ 2 ]

2 голосов
/ 07 января 2011

Вы не можете использовать Func, вам нужно использовать Expression<Func>.

+ можно сделать через Expression.And.

Обновление (не тестировалось):

Expression<Func<vwMailMerge, bool>> whereClause = null;
...
Expression<Func<vwMailMerge, bool>> MailMergeWhereClause(
   params Expression<Func<vwMailMerge, bool>>[] wheres)
{
  if (wheres.Length == 0) return x => true;
  Expression result = wheres[0].Body;
  for (int i = 1; i < wheres.Length; i++)
  {
    //probaby needs a parameter fixup, exercise for reader
    result = Expression.And(result, wheres[i].Body); 
  }
  return Expression.Lambda<Func<vwMailMerge,bool>>(result, wheres[0].Parameters);
}

Обновление 2:

Вышеупомянутый подход не работает, как я ожидал. Это может быть легко решить в .NET 4 с использованием класса ExpressionVistor. Для .NET 3.5 (или если вышеупомянутое слишком сложно) должно работать следующее.

Подход заключается в добавлении предложений where в IQueryable напрямую, чтобы вы получили:

somequery.Where(x => x.foo).Where(x => x.bar).Where(x => x.baz)

Итак, вы можете просто добавить их по мере необходимости, но это потребует некоторых изменений в логике / потоке вставленного вами кода.

0 голосов
/ 07 января 2011

Вы могли бы лучше переформатировать свой вопрос с помощью инструмента кода.

Однако, похоже, вы могли бы подойти к проблеме таким образом, чтобы избежать появления всех этих функциональных выражений:

this.ObjectContext.vwMailMerges.Where(mm=>IsValidMailMerge(mm,personType)).ToList()


private bool IsValidMailMerge(YourType mailmerge, YourType2 personType)
{
if(...) // type specific criteria here
return true;
else
return false;
}
...