#linq #.net-core #entity-framework-core
#linq #.net-core #entity-framework-core
Вопрос:
Я новичок в Entity Framework и LINQ и изо всех сил пытаюсь «преобразовать» свой SQL-запрос в его синтаксис.
Приведена таблица, содержащая производственные заказы с OrderNumber
, Quantity
Material
и т.д. в качестве столбцов. Кроме того, есть столбец Timestamp
.
Если количество заказа будет обновлено, это приведет к появлению совершенно новой записи в таблице, где все значения будут такими же, как в предыдущей строке, за исключением Timestamp
(указывающего время изменения) и Quantity
(содержащего новое значение). Это позволяет мне иметь «историю» заказа.
Выбор только последней версии определенного заказа с использованием SQL может выглядеть следующим образом:
SELECT p1.*
FROM dbo.ProductionOrders as p1
JOIN (SELECT OrderNumber, MAX(Timestamp) as Timestamp FROM dbo.ProductionOrders GROUP BY OrderNumber) as p2
on p1.OrderNumber = p2.OrderNumber and p1.Timestamp = p2.Timestamp
WHERE p1.OrderNumber = 'order-182736'
Та же функциональность, которую я реализовал в своем коде на C #, выглядит следующим образом:
var productionOrder = _db.ProductionOrders.Where(po =&&t; po.OrderNumber == "order-182736")
.OrderByDescendin&(po =&&t; po.Timestamp)
.FirstOrDefault();
Я теряюсь, когда хочу получить несколько строк. Например, все заказы на определенный материал. Используя SQL, мне нужно только настроить WHERE
условие:
SELECT p1.*
FROM dbo.ProductionOrders as p1
JOIN (SELECT OrderNumber, MAX(Timestamp) as Timestamp FROM dbo.ProductionOrders GROUP BY OrderNumber) as p2
on p1.OrderNumber = p2.OrderNumber and p1.Timestamp = p2.Timestamp
WHERE p1.Material = 42
Примеры, которые я нашел для JOIN
использования LINQ, не работают с вложенными запросами (мой основной источник microsoft.com)
Как я могу получить все последние «версии» заказов на определенный материал с помощью LINQ?
Ответ №1:
Вы можете сделать это точно так же, как в SQL. _db.ProductionOrders
в LINQ к сущностям представляет dbo.ProductionOrders
в SQL, и вы можете использовать его как на верхнем уровне, так и на уровне подзапроса:
var query = _db.ProductionOrders
.Join(_db.ProductionOrders
.GroupBy(p2 =&&t; new { p2.OrderNumber })
.Select(& =&&t; new { &.Key.OrderNumber, Timestamp = &.Max(e =&&t; e.Timestamp) }), // subquery
p1 =&&t; new { p1.OrderNumber, p1.Timestamp }, p2 =&&t; p2, // join condition
(p1, p2) =&&t; p1) // result selector (p1.*)
.Where(p1 =&&t; p1.Material == 42);
(Примечание: не уверен, откуда Label
берется информация в ваших SQL-запросах, поэтому использую OrderNumber
вместо этого).
или, если вы предпочитаете, то же самое в синтаксисе запроса LINQ:
var query =
from p1 in _db.ProductionOrders
join p2 in (from p2 in _db.ProductionOrders
&roup p2 by new { p2.OrderNumber }) into &
select new { &.Key.OrderNumber, Timestamp = &.Max(p2 =&&t; p2.Timestamp) })
on new { p1.OrderNumber, p1.Timestamp } equals p2
where p1.Material == 42
select p1;
Комментарии:
1.
Label
все еще был там из-за некоторых ошибок копирования и вставки, которые я допустил, я изменил OP. Мне нужно некоторое время, чтобы разобраться в LINQ…