Im trying to query my OData webservice from a C# application.
When i do the following:
var SecurityDefs = from SD in nav.ICESecurityDefinition.Take(1)
orderby SD.Entry_No descending
select SD;
i get an exception because .top() and .orderby is not supposed to be used together.
I need to get the last record in the dataset and only the last.
The purpose is to get the last used entry number in a ledger and then continue creating new entries incrementing the found entry no.
I cant seem to find anything online that explains how to do this.
Its very important that the service only returns the last record from the feed since speed is paramount in this solution.
Where did you read that? In general
.top()
or.Take()
should ONLY be used in conjunction WITH.orderby()
, otherwise the record being retrieved is not guaranteed to be repeatable or predictable.Probably the compounding issue here is mixing query and fluent expression syntax, which is valid, but you have to understand the order of precedence.
Your syntax is taking 1 record, then applying a sort order... you might find it easier to start with a query like this:
This can be executed on a single line using brackets, but you can see how the query is the same in both cases,
SecurityDefs
in this case is a singleICESecurityDefinition
typed record, where asSecurityDefsDeferred
is anIQueryable<ICESecurityDefinition>
that only has a single record.If you only need the record itself, you this one liner:
You can execute the same query using fluent notation as well:
In both cases,
.Take(1)
or .top() is being implemented through.FirstOrDefault()
. You have indicated that speed is important, so use.First()
or.FirstOrDefault()
instead of.Single()
or.SingleOrDefault()
because the single variants will actually request.Take(2)
and will throw an exception if it returns 1 or no results.If the record being returned has many columns, and you are only interested in the
Entry_No
column value, then perhaps you should simply query for that specific value itself:Query expression:
Fluent expression:
If Speed is paramount then look at providing a specific custom endpoint on the service to either serve the record or do not process the 'Entry_No` in the client at all, make that the job of the code that receives data from the client and compute it at the time the entries are inserted.
Making the query perform faster is not the silver bullet you might be looking for though, Even if this is highly optimised, your current pattern means that
X
number of clients could all call the service to get the current value ofEntry_No
, meaning all of them would start incrementing from the same value.If you MUST increment the
Entry_No
from the client then you should look at putting a custom endpoint on the service to simply return the NextEntry_No
to use. This should be optimistic meaning that you don't care if theEntry_No
actually gets used in the end, but you can implement the end point such that every call will increment the field in the database and return the next value.