Reputation: 30454
Addition after comment, my question was not clear enough
Some software accessed a database and retrieved a collection of items. He selected a subset of them and called me to ask to process the collection. Between the other software's access to the database and its call to me items might be removed by others.
Other Process:
IEnumerable<MyType> itemsToProcess = FetchItemsToProcess();
Process(itemsToProcess);
My procedure:
void Process(IEnumerable<MyType> items)
{
...
}
The collection of items
is fairly small, and normally all items are expected to be present in the database, with unchanged primary and foreign keys, However I can't be sure whether all items still exist.
Continuing original question
It is not a problem if during processing I detect that an item does not exist in the database anymore, it is only a waste of time. Therefore before processing I want to check if all items exist in the database.
I have checked that all items in my sequence have a non-zero ID. Now I need to check if all IDs are IDs of existing items in the database:
Not efficient solution: get the Ids of all existing items into local memory and use Except
IEnumerable<MyType> itemsToProcess = ...
IEnumerable<int> idsToProcess = itemsToProcess.Select(item => item.Id);
IEnumerable<int> existingIds = myDbContext.MyItems.Select(item => item.Id);
bool nonExistingItemsDetected = idsToProcess.Except(existingIds).Any();
The following method requires one DB accesses per item to check:
IEnumerable<MyType> itemsToProcess = ...
IEnumerable<int> idsToProcess = itemsToProcess.Select(item => item.Id);
bool nonExistingItemsDetected = idsToProcess
.Where(idToProcess => !myDbContext.MyItems.Any(item => item.Id == idToProcess);
Because the sequence of items to process is fairly small I'd like to use the database to detect if any ID does not exist. I think I need to make an IQueryable
with a Contains
bool nonExistinItemsDetected = myDbContext.MyItems
.Any( ?? )
What predicate can I use to detect if idsToProcess contains ids of items that do not exist.
Upvotes: 0
Views: 1963
Reputation: 9002
If you need to process the items anyway, you'll need to get them from the database. In which case, you might as well use something like the following to obtain the matching items:
var existingDbItems = dbContext.MyItems.Where(i => localIdCollection.Contains(i.Id));
Then you can simply check that the count of distinct id's matches the number of records returned before proceeding.
Ensure the collection of id's that you use .Contains()
on is an in-memory collection (not a store expression) otherwise you may see an exception.
EDIT
Based on your comment, you could change the query above to:
var existingDbItemsCount = dbContext.MyItems
.Where(i => localIdCollection.Contains(i.Id)).Distinct().Count();
So that you're only obtaining the count, rather than all the records.
If the items are so volatile that you have to check they exist at this point, unless you're working within a transaction, there still may be problems by the time your code modifies the database.
Upvotes: 1