tags:

views:

109

answers:

3

I have a first query that returns a set of entities:

var resultSet = ....query....ToList();

which would return A, B, C, D, E

The entities inside this set are organized into chains because they have a reference (prevEntityId) pointing to the same type of entity, i.e.:

A -> B -> D

C -> E

I would like to write a second query so that only A and C are now returned but I have no idea how to write it.

I would prefer your answer with linq methods (like .Where()) instead of the new linq syntax.

Thank you

Update: sorry I initially used the wrong vocabulary in my question with the term "foreign key". Actually an entity has a direct reference to the previous entity so to elect an entity in the second query, there must be no other entity that references it. I thought it would take 2 queries but if you think it can be done in one...

A: 

I am not 100% clear on your entities and their relationships, but this will get you started.

It sounds like you're trying now to further query from your resultSet object. If wanting A and C, then it sounds like the FK would be null.

var cEntities = resultSet.Where(e=>e.prevEntityID == null).ToList();
p.campbell
sorry, I described my issue incorrectly. See the update. Your answer would produce D and E.
Nicolas Cadilhac
+1  A: 

EDIT: Okay, as the relationship is the opposite of what I expected, you're looking for entities such that no entity has it as the previous one.

One option:

 Where(x => !fullList.Any(y => y.PrevEntityId == x.Id));

Now, if your query is actually being executed in SQL it would be worth seeing what that generates - it may well not be efficient. It pretty definitely won't be efficient in LINQ to Objects. For LINQ to Objects, you'd be better off with:

 HashSet<string> prevIds = new HashSet<string>(fullList.Select(x => x.PrevId));
 var heads = fullList.Where(x => !prevIds.Contains(x));

If you could more information about your environment, that would help us to help you.

Jon Skeet
sorry, I described my issue incorrectly. See the update. Your answer would produce D and E.
Nicolas Cadilhac
I'm not in a testable environment so I can't test your solution right away but your second solution satisfies me, at least in theory. As soon as I can proove it with my data, I will accept your answer.
Nicolas Cadilhac
A: 

You could write a helper function that given the last entity in a chain gives you the first entity. Then you can combine that with pcampbell's answer to get the first entities in a chain. Something along these lines

resultSet.Where(e=>e.prevEntityID == null).Select(e => GetHead(e, resultSet)).ToList();

Entity GetHead(Entity current, List<Entity> entities)
{
    Entity next = entities.Where(e => e.prevEntityID = current.id).FirstOrDefault();

     if (next == null)
        return current;
     else
        return GetHead(next, entities);
}
Joshua
I understand this may work but I Wanted to avoid such a solution and thought a query could exist to achieve the same thing.
Nicolas Cadilhac