Reputation: 4713
I have an MS SQL table with the following fields. I am using entity framework:
EntryId
EntryType
Operation
UpdatedTime_UTC
The EntryId and EntryType fields can contain duplicate values. When an object is created a record is added and its “operation” field will be set to “added”. If the object is modified another record is written with the same EntryId and EntryType values as the first record but the “operation” field will be set to “modified”. When the object is deleted (you’ve guessed it), another record is written with the same EntryId and EntryType values as the previous records but the “operation” field will be set to “deleted”.
Some example data is shown below:
ID1, Type1, “added”, 2012-08-20 09:15:50
ID2, Type1, “added”, 2012-08-21 09:15:50
ID1, Type1, “modified”, 2012-08-22 09:15:50
ID1, Type1, “modified”, 2012-08-23 09:15:50
ID2, Type1, “deleted”, 2012-08-24 09:15:50
This shows information about two objects (ID1 and ID2). Both were added to the table but ID1 was modified and ID2 was deleted. As part of a reconcile procedure I need to check that if an object has been deleted there must be a record in my table with a matching EntryId that has an operation set to “deleted”. If there isn’t my code will add one.
Now to my problem. I have a function that is called when my system believes that there are no objects for a given “EntryType”. I need to confirm that all the records in my table for that “EntryType” have a record with an “operation” set to “deleted”. In the data shown above “ID1” doesn’t have a “deleted” entry. This is fine if the object still exists but bad if the object has gone. I am using the following Linq to get a grouped list where I pass in the “entityType” I am interested in.
var item = _ctx.JournalSet
.Where(x => x.EntryType == entityType)
.OrderBy(x => x.UpdatedTime_UTC)
.GroupBy(x => x.EntryId);
I then use this code to look into each group to see that it has a “deleted” entry. If it doesn’t I add a new record to my table.
foreach (var item in result)
{
if (item.Last().Operation != "deleted")
{
// no 'deleted' entry found. time to add a new entry.
}
}
What I would like to do is to modify my Linq statement so that it only returns the EntryId and EntryType details when a deleted entry needs to be added.
Additional information: A deleted record will always have a datetime later than an “add” or “modify” record so when ordering by “UpdatedTime_UTC” the last entry should be a “deleted” one if it exists for the given entryId
Is it possible to create a Linq statement to do the above without the need for the foreach stuff?
Upvotes: 1
Views: 99
Reputation: 564433
I would find the records where you are missing deleted entries, then add them as needed:
var itemsToAdd = _ctx.JournalSet
.Where(x => x.EntryType == entityType)
.OrderBy(x => x.UpdatedTime_UTC)
.GroupBy(x => x.EntryId)
.Where(grp => grp.Last().Operation != "deleted");
You could then use a foreach
to add the items, or even do this via a second LINQ Select
statement (to map to the new type), depending on the collection where you're adding. The second statement would likely be something like:
collection.AddRange(itemsToAdd.Select(grp => new YourType(grp.Key.EntryId, "deleted")));
(This was done assuming a constructor which takes an ID + "deleted", edit as needed...)
Upvotes: 0
Reputation: 25835
Have you tried something like this?
var item = _ctx.JournalSet
.Where(x => x.EntryType == entityType)
.OrderBy(x => x.UpdatedTime_UTC)
.GroupBy(x => x.EntryId)
.Where(y => y.Last().Operation != "deleted");
Upvotes: 2