Запрос подключенной службы ODataV4 с помощью LINQ — получение последней записи из таблицы
Я пытаюсь запросить мой веб-сервис OData из приложения С#.
Когда я делаю следующее:
var SecurityDefs = from SD in nav.ICESecurityDefinition.Take(1)
orderby SD.Entry_No descending
select SD;
я получаю исключение, потому что .top() и .orderby не должны использоваться вместе.
Мне нужно получить последнюю запись в наборе данных и только последнюю.
Цель состоит в том, чтобы получить последний использованный номер записи в книге, а затем продолжить создание новых записей, увеличивая найденный номер записи.
Кажется, я не могу найти в Интернете ничего, что объясняет, как это сделать.
Очень важно, чтобы сервис возвращал только последнюю запись из фида, так как скорость имеет первостепенное значение в этом решении.
1 ответ
я получаю исключение, потому что .top() и .orderby не должны использоваться вместе.
Где ты это прочитал? В целом
.top()
или же
.Take()
следует использовать ТОЛЬКО в сочетании с
.orderby()
, в противном случае не гарантируется, что извлекаемая запись будет повторяемой или предсказуемой.
Вероятно, проблема здесь заключается в смешивании синтаксиса запроса и свободного выражения, что является допустимым, но вы должны понимать порядок приоритета.
Ваш синтаксис принимает 1 запись, а затем применяет порядок сортировки... вам может быть проще начать с такого запроса :
// build your query
var SecurityDefsQuery = from SD in nav.ICESecurityDefinition
orderby SD.Entry_No descending
select SD;
// Take the first item from the list, if it exists, will be a single record.
var SecurityDefs = SecurityDefsQuery.FirstOrDefault();
// Take an array of only the first record if it exists
var SecurityDefsDeferred = SecurityDefsQuery.Take(1);
Это можно выполнить в одной строке, используя скобки, но вы можете видеть, что запрос одинаков в обоих случаях,
SecurityDefs
в данном случае один
ICESecurityDefinition
типизированная запись, где как
SecurityDefsDeferred
является
IQueryable<ICESecurityDefinition>
который имеет только одну запись.
Если вам нужна только сама запись, вам нужен один вкладыш:
var SecurityDefs = (from SD in nav.ICESecurityDefinition
orderby SD.Entry_No descending
select SD).FirstOrDefault();
Вы также можете выполнить тот же запрос, используя беглую нотацию:
var SecurityDefs = nav.ICESecurityDefinition.OrderByDescending(sd => sd.Entry_No)
.FirstOrDefault();
В обоих случаях,
.Take(1)
или .top() реализуется через . Вы указали, что скорость важна, поэтому используйте
.First()
или же
.FirstOrDefault()
вместо
.Single()
или же
.SingleOrDefault()
потому что отдельные варианты на самом деле будут запрашивать
.Take(2)
и выдаст исключение, если он вернет 1 или не вернет никаких результатов.
Варианты OrDefault для обоих этих запросов не повлияют на производительность самого запроса и должны иметь незначительное влияние на ваш код, используйте тот, который подходит для вашей логики, которая использует возвращенную запись, и если вам нужно обработать случай, когда есть нет существующей записи.
Если возвращаемая запись имеет много столбцов, и вас интересует только значение столбца, то, возможно, вам следует просто запросить это конкретное значение:
Выражение запроса :
var lastEntryNo = (from SD in nav.ICESecurityDefinition
orderby SD.Entry_No descending
select SD.Entry_No).FirstOrDefault();
Плавное выражение :
var lastEntryNo = nav.ICESecurityDefinition.OrderByDescending(sd => sd.Entry_No)
.Select(sd => sd.Entry_No)
.FirstOrDefault();
Если скорость имеет первостепенное значение , рассмотрите возможность предоставления конкретной пользовательской конечной точки в службе, чтобы либо обслуживать запись, либо вообще не обрабатывать «Entry_No» в клиенте, сделайте это заданием кода, который получает данные от клиента и вычисляет их. в момент вставки записей.
Ускорение выполнения запроса — это не серебряная пуля, которую вы, возможно, ищете. Даже если это сильно оптимизировано, ваш текущий шаблон означает, что
X
несколько клиентов могут вызвать службу, чтобы получить текущее значение , что означает, что все они начнут увеличиваться с одного и того же значения.
Если вы ДОЛЖНЫ увеличить значение от клиента , вам следует подумать о добавлении пользовательской конечной точки в службу, чтобы просто вернуть Next для использования. Это должно быть оптимистичным , означающим, что вас не волнует, если
Entry_No
фактически используется в конце, но вы можете реализовать конечную точку так, чтобы каждый вызов увеличивал поле в базе данных и возвращал следующее значение.
Это немного выходит за рамки вашего первоначального поста, но SQL Server теперь поддерживает последовательности , которые формализуют этот тип логики с точки зрения базы данных и схемы, использование последовательности упрощает управление этими типами приращений от клиента, потому что мы больше не полагаемся на то, что результаты обновлений данных будут зафиксированы в таблице до того, как клиент сможет увеличить следующую запись. (это то, что ваш
TOP
,Order By
Desc
решение пытается сделать.