2012-02-08 3 views
4

У меня есть запрос linq-to-sql, который я использую, чтобы заполнить объект, который имеет ints как свойства и функция которого должна содержать count.linq to sql where clause и counting

Запрос выглядит следующим образом (на данный момент)

var TheQuery = from..... 
       where .... 
       in thefilteredresults 
       select new MyModel() 
       { 
        Total = thefilteredresults.Count(), 

        TotalTime = (from x in thefilteredresults 
           where x.Outcome == 4).Sum(t => t) 
       }.Single(); 

Я есть некоторые проблемы фильтрации первого и затем подсчета на основе отфильтрованных результатов первоначальных где положений. Что мне нужно изменить?

Спасибо.

+0

Откуда берутся результаты, и на что это похоже? – StriplingWarrior

+0

filterresult - результат предложений from и where; Я фильтруюсь по идентификатору пользователя и дате времени, а затем делаю подсчет только по этим записям. – frenchie

ответ

5

Вы можете взломать это вместе:

(from x in table 
where filter(x) 
group x by 0 into g 
select new { Count = (int?)g.Count() ?? 0, Sum = (int?)g.Sum(x => x.Value) ?? 0 }).Single() 

SQL Server оптимизирует из ненужной группировки , Вероятно, лучше всего документировать, почему вы написали это так.

Редактировать: Я включил странно выглядящий актер в int. Причина этого заключается в том, чтобы сказать Linq to SQL предположить, что значение имеет значение NULL и использовать вызов функции COALELCE для преобразования NULL в 0. Это взлом, который также должен быть документирован.

+0

Просто уточните: это решение сделает однократное путешествие в базу данных. Это будет более эффективно, чем два запроса. – usr

+0

Мне нравится концепция. Поскольку я фильтрую UserID в предложении where, я переписал предложение группы «group x by x.UserID в g», и это работает. Теперь проблема заключается в том, что иногда группа пуста, и поэтому счетчик возвращает null и запрос сбой. Как я могу сказать «получить счет или получить 0, если ничего нет»? – frenchie

+0

Я забыл предупредить вас об этом. Я добавил код. – usr

1

Поскольку вы действительно только ищете один результат, это, вероятно, самый простой подход:

var filteredResults = from .... 
         where .... 
         select ....; 
var myModel = new MyModel{ Total = filteredResults.Count(), ... }; 
+0

Спасибо, я вижу, как это может сработать, приведя все записи из db, а затем выполнив агрегацию в linq-to-objects. Мне было интересно, есть ли способ сделать это в linq-to-sql, без необходимости возвращать все результаты из db. – frenchie

+1

@frenchie: Вы на самом деле не приносите все в память и считаете оттуда, это лениво загружено. –

+1

Я не вижу, что здесь тут же загружается. Если бы это было бы еще хуже: это вызовет проблему SELECT N + 1. – usr