tags:

views:

60

answers:

3
var nodes = (from n in db.Nodes
                 join st in db.SessionTrackings on n.NodeID equals st.NodeID
                 where st.UserID == userid && st.GroupID == groupid
                 select n);

IDictionary<int, bool> trackingData = new Dictionary<int, bool>();

foreach (Node n in nodes)
{
    trackingData.Add(new KeyValuePair<int, bool>(n.ID, true));
}

I keep getting a 'that key was already added' because there could be many SessionTrackings per Node, however I just want to get back all the Nodes that have at least 1 SessionTracking in existence for the NodeID but I don't need to get the Nodes more than once. If there are 4000 SessionTrackings for a Node (say ID = 45) I still only one 1 instance of Node 45 in my IQueryable. How can I modify my query for this? Please don't worry about why I need it in a Dictionary that's just the way it is.

+1  A: 

You just need to tell the query engine that you only want distinct instances of your objects:

var nodes = (from n in db.Nodes 
             join st in db.SessionTrackings on n.NodeID equals st.NodeID 
             where st.UserID == userid && st.GroupID == groupid 
             select n).Distinct();

IDictionary<int, bool> trackingData = nodes.ToDictionary(n => n.ID, n => true);

If you don't need the nodes query for anything else, you can combine the statements like this:

IDictionary<int, bool> trackingData =
            (from n in db.Nodes 
             join st in db.SessionTrackings on n.NodeID equals st.NodeID 
             where st.UserID == userid && st.GroupID == groupid 
             select n.Id)
            .Distinct()
            .ToDictionary(i => i, i => true);
Gabe
It looks like the OP actually wants a dictionary of tracking ids (`a.ID`) to bools. Which means the OP should really just be using a HashSet<int>(), passing your `trackings` result to the constructor. (Though with a further select if the OP actually wants the ID instead of the object)
Kirk Woll
I agree that a dictionary mapping id -> true is a lot like a HashSet, but he probably needs to pass that dictionary to some other component he doesn't control (or sometimes needs to set the values to false).
Gabe
@Gabe, to set the "values to false" in the HashSet analogy would simply mean the removal of the items from the HashSet.
Kirk Woll
Kirk: A HashSet gives you 2 states for any object: either in the set or not; the Dictionary gives you 3 states: either in the dictionary and true or false or not in the dictionary. It's not hard to imagine a situation where you need 3 states instead of 2.
Gabe
A: 

This is how you can get the first session:

var nodes = (from n in db.Nodes 
    join st in db.SessionTrackings on n.NodeID equals st.NodeID 
    where st.UserID == userid && st.GroupID == groupid 
    select n)
    .GroupBy(n => n.ID)
    .Select(g => g.First());
Igor ostrovsky
A: 

I think you would need to do something like

var nodeids = (from n in db.Nodes
join st in db.SessionTrackings on n.NodeID equals st.NodeId
where  st.UserId.equals(userid) && st.GroupID.equals(groupid)
select new {Id = n.Id})).distinct();

That should give you everything you need for the iteration, without repeats.

Hal