Выражение «или» вместе <Func <EntityFramework Entity, bool >> в .NET 4, доменная служба Silverlight RIA - PullRequest
1 голос
/ 22 октября 2010

У меня есть небольшой пользовательский объект, определенный как:

public class TimeSeriesDefinition
{  
    public int classID;
    public DateTime startTime;
    public DateTime endTime;
}

Я передаю список ClassIDs, List startTimes и List endTimes в функцию RIA Domain Service.В порядке организации я сгруппировал эти значения в List of TimeSeriesDefinitions, а затем попытался использовать цикл foreach для создания выражения, которое будет выбирать с помощью операторов AND между значениями в классе и операторов OR между каждым классом или реализовывать "..Any "запрос, как предложено первым ответом, который я получил ниже.Проблема в том, что я не могу использовать класс TimeSeriesDefinition в функции DomainService, потому что это не примитивный тип или один из моих типов сущностей (может быть, я должен просто создать сущность с этим типом?), Поэтому мне нужен другой метод достиженияжелаемые результаты запроса.Моя оригинальная идея использования выражений, с которыми я никогда не получал, заключается в следующем:

        Expression<Func<EventLog, bool>> bounds;
        Boolean assignedBounds = false;
        foreach (TimeSeriesDefinition ts in reporters)
        {
            if (assignedBounds.Equals(false))
            { 
                bounds = c => c.reporterID == ts.classID && c.reportDateTime >= ts.startTime && c.reportDateTime <= ts.endTime; 
                assignedBounds = true;
            }
            else
            { 
                Expression<Func<EventLog, bool>> newBounds = c => c.reporterID == ts.classID && c.reportDateTime >= ts.startTime && c.reportDateTime <= ts.endTime;
                bounds = Expression.Or(Expression.Invoke(bounds), Expression.Invoke(newBounds);
                // bounds = Expression<Func<EventLog, bool>>.Or(bounds, newBounds);
            }
        }

        return this.ObjectContext.EventLog.Where(bounds);

Моя цель - чтобы в наборе результатов были все записи ts.classID между ts.startDate и ts.EndDate.Из того, что я обнаружил в Интернете, кажется, что убедиться, что параметры правильно назначены, тоже сложно, но сейчас я все еще получаю

"Не могу неявно преобразовать тип" System.Linq.Expressions.BinaryExpression 'to' System.Linq.Expressions.Expression> '"

ошибка в строке

 bounds = Expression.Or(Expression.Invoke(bounds), Expression.Invoke(newBounds);

Может кто-нибудь указать мне правильное направление?Я полагаю, что мог бы как-то встроить все это в строку запроса, но я бы предпочел не идти туда.

Заранее спасибо за понимание!

Ответы [ 2 ]

2 голосов
/ 06 ноября 2010

Если вы Funcletize (локализуете) свои ссылки на TimeSeriesDefinition на стороне клиента, вы сможете включить их в свой запрос (см. Здесь метод Evaluator.PartialEval http://msdn.microsoft.com/en-us/library/bb546158.aspx). Вы должны просто вызвать егона вашем объекте Expression, и ссылки на TimeSeriesDefinitions перенесены в примитивные константы:

Evaluator.PartialEval(lambdaExpression);

Что касается вашей проблемы компиляции:

bounds = Expression.Or(Expression.Invoke(bounds), Expression.Invoke(newBounds);

Левая часть этого назначения является универсальнойLambdaExpression. Правая сторона - BinaryExpression. Чтобы выполнить назначение, вам нужно лямбда-оператор Or, а также предоставить ParameterExpression для ваших InvocationExpressions:

var parameterExpression = Expression.Parameter(typeof(EventLog));
bounds = Expression.Lambda<Func<EventLog, bool>>(  
    Expression.Or(  
         Expression.Invoke(bounds, parameterExpression),  
         Expression.Invoke(newBounds, parameterExpression), 
    parameterExpression);

Однако ... вы, вероятно, столкнетесь с замечательнымтот факт, что RIA не поддерживает InvocationExpressions ... (я не проверял это, но я знаю, что EF не поддерживает.) Вы должны расширить свои InvocationExpressions, чтобы встроить их (что-то вроде описанного выше Funcletlizer).

LINQKit (http://www.albahari.com/nutshell/linqkit.aspx) обеспечивает один изэлектронная коробка.Он также предоставляет вспомогательные методы для объединения критериев, как вы упомянули выше.Если вы не хотите полностью зависеть от LINQKit, вы можете получить исходный код для той же вещи: http://www.java2s.com/Open-Source/CSharp/Content-Management-Systems-CMS/Kooboo/Microsoft/Data/Extensions/DataExtensions.cs.htm

Затем просто измените свой Куда:

return this.ObjectContext.EventLog.Where(InvocationExpander.Expand(bounds));
2 голосов
/ 22 октября 2010

Вместо List<TimeSeriesDefinition> вы можете использовать List<Tuple<int, DateTime, DateTime>>. Тогда ваш запрос будет таким ...

return ObjectContext.EventLog.Where(c =>
           reporters.Any(r =>
               c.reporterID == r.Item1 &&
               c.reportDateTime >= r.Item2 &&
               c.reportDateTime <= r.Item3));
...