Reputation: 1425
I have a list of entities coming from an external source. I need to compare it to what I already have, and only add the ones that don't exist. Pseudo code below.
var newVersions = item.Versions
.Where(s => db.ExistingVersions
.Select(t=>t.versionID)
.DoesNotContains(s.versionID));
That obviously doesn't work, and I'm not sure how to fix it. I don't want to use a for loop because I believe that would mean I would have hundreds of database hits just to check the versions on each item. I am loading multiple items, each item has as many as 100 versions.
Upvotes: 1
Views: 4598
Reputation: 134
public async Task<bool> IsExistBy(List<int> ids, CancellationToken ct)
{
var temp = await _repository.TableNoTracking.Where(x=>ids.Contains(x.Id)).ToListAsync(ct);
return temp.Count == ids.Count;
}
Upvotes: 0
Reputation: 14328
If there's nothing more to the question than I think, then it shouldn't be complicated.
Assuming that VersionID
is unique identifier, then you can do this:
var existingVersions = db.ExistingVersions.Select(x => x.VersionID).ToList();
mind you, for Contains
it would be better to:
var existingVersions = new HashSet(db.ExistingVersions.Select(x => x.VersionID).ToList());
[EDIT]: Per Magnus's comment, you can drop the ToList
from above code snippet.
and then:
var newVersions = items.Versions.Where(x => !existingVersions.Contains(x.VersionID));
This is probably the most performant, 'cause when calling the database, you select only the VersionID
. Other option involves writing a custom IEqualityComparer<T>
and using Except
, but you'd have to pull everything from the DB which may be more costly.
Upvotes: 7
Reputation: 24433
You could try something like this:
// in memory: get list of potential version ids
var potentialIds = item.Versions.Select( o => o.versionID ).ToList();
// hit database ( once ) : get existing version ids
var existingIds = db.ExistingVersions
.Where( o => potentialIds.Contains( o.versionID ) )
.Select( o => o.versionID )
.ToList();
// in memory: filter potential objects
var newVersions = item.Versions
.Where( o => !existingIds.Contains( o.versionID ) )
.ToList();
// database inserts:
foreach( var newVersion in newVersions )
{
...
One thing to bear in mind is that this is not thread-safe: if something else is adding ExistingVersion
rows at the same time, you may try to insert a record that was added after you checked the database.
Upvotes: 3