Использование Linq для возврата последних 3,4 ... n заказов для каждого клиента - PullRequest
1 голос
/ 05 апреля 2011

У меня есть база данных с заказами клиентов.Я хочу использовать Linq (для EF), чтобы запросить базу данных, чтобы вернуть последние (самые последние) 3,4 ... n заказов для каждого клиента.

Примечание: Клиент 1, возможно, только что сделал 12 заказовв последний час;но клиент 2, возможно, не сделал ничего с прошлой недели.

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

Есть хорошие идеи?

Редактировать: Заказчики и заказы - это упрощение.Таблица, которую я запрашиваю, на самом деле является записью исходящих сообщений для различных веб-сервисов.Просто казалось, что проще описать как клиентов, так и заказы.Отношения такие же.Я строю задачу, которая проверяет последние n сообщений для каждого веб-сервиса, чтобы увидеть, были ли какие-либо сбои.Мы хотим получить статус работоспособности веб-сервисов в реальном времени.

@ CoreySunwold
Моя таблица выглядит примерно так:
MessageID, WebserviceID, SentTime, Status, Message, Error,

Или из контекста клиента / заказа, если это делает его более легким:
OrderID, CustomerID, StatusChangedDate, Status, WidgetName, Комментарии

Edit 2: В конце концов я кое-что разработал
(Шляпа для @StephenChung, который в основном придумал то же самое, но в классическом linq)

var q = myTable.Where(d => d.EndTime > DateTime.Now.AddDays(-1))<br> .GroupBy(g => g.ConfigID)<br> .Select(g =>new { ConfigID = g.Key, Data = g.OrderByDescending(d => d.EndTime) .Take(3).Select(s => new { s.Status, s.SentTime }) }).ToList();

Это займет некоторое время, чтобы выполнить.Поэтому я не уверен, является ли это наиболее эффективным выражением.

Ответы [ 6 ]

2 голосов
/ 05 апреля 2011

Это должно дать 3 последних заказа каждого клиента (если они есть):

from o in db.Orders
group o by o.CustomerID into g
select new {
  CustomerID=g.Key,
  LastOrders=g.OrderByDescending(o => o.TimeEntered).Take(3).ToList()
}

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

Если вам нужно оптимизировать, вам придется вручную создать SQL, чтобы он возвращал только последние 3, а затем сделать его в представлении.

2 голосов
/ 05 апреля 2011

Вы можете использовать SelectMany для этой цели:

customers.SelectMany(x=>x.orders.OrderByDescending(y=>y.Date).Take(n)).ToList();
0 голосов
/ 05 апреля 2011

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

select 
    *
    ,RANK() OVER  (PARTITION BY c.id ORDER BY o.order_time DESC) AS 'RANK'
from 
    customers c 
inner join 
    order o
on 
    o.cust_id = c.id
where 
    RANK < 10 -- this is "n"

Я не использовал этот синтаксис некоторое время, поэтому он может быть не совсем правильным, но если я понимаю вопрос, то я думаю, что это лучшийподход.

0 голосов
/ 05 апреля 2011
var ordersByCustomer = 
db.Customers.Select(c=>c.Orders.OrderByDescending(o=>o.OrderID).Take(n));

Это вернет заказы, сгруппированные по клиенту.

0 голосов
/ 05 апреля 2011
var orders = orders.Where(x => x.CustomerID == 1).OrderByDescending(x=>x.Date).Take(4);

Это займет последние 4 заказа.Конкретный запрос зависит от вашей таблицы / структуры объекта.

Кстати: вы можете взять x в качестве заказа.Таким образом, вы можете прочитать это так: Получить заказы, где order.CustomerID равен 1, OrderThem по order.Date и взять первые 4 «строки».

0 голосов
/ 05 апреля 2011

Как насчет этого? Я знаю, что это будет работать с обычными коллекциями, но не знаю об EF.

yourCollection.OrderByDescending(item=>item.Date).Take(n);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...