I have a list of plans and a list of contacts, and I have to check whether contact.ProviderId matches plan.ProviderId. If they match I need to store in a contactUI the plan.Name.

Provider to plan is a 0..1-to-many relationship, and that's why I couldn't use the Dictionary I tried at first instance.

For retrieving the list of object I need to call the DB. So I want to avoid calling it more than needed.

I came up with this

var offeredPlans = new List<Tuple<int, string>>();
foreach (var plan in plans)
    // ....Some code...
    offeredPlans .Add(new Tuple<int, string>(providerId, plan.Name));

var compareTo = offeringPlans.ToLookup(pair => pair.Item1, pair => pair.Item2);

foreach(var contact in contacts)
    var plansAttachedTo = Check(providerId.Value, compareTo);

    foreach (var plan in plansAttachedTo)
        // New contactUI with plan.Name as one of its properties 


private static IEnumerable<string> Check(int providerId, ILookup<int, string> plans)
    return offeringPlans.Where(p => p.Key == providerId).SelectMany(p => p);

Is this terrible or does it make sense?

  1. I've never used before these classes (Tuple, Lookup...)
  2. I would like my code to be the clearest I can even it it's not the cleverest of the solution I can think of which is not this case for sure, actually I realize now I could have done some kind of SQL joins, right? (but I would like to know if someone can point any obvious error in the current code).


The code inside the loop is this one (in this case I don't even omit code as I'm not sure if it's possible what you suggest p.s.w.g). I am using reflection as only some of the classes that inherit from plan have the ProviderId property.

foreach (var plan in plans)
    var offeringDetail = new OfferingDetail();

    if (plan.GetType() == typeof (OwnedProductSummary))
        var productSummary = plan as OwnedProductSummary;

        offeringDetail = _offeringBLL.GetById(productSummary.OfferingID);

    if (plan.GetType() == typeof (OwnedServiceSummary))
        var serviceSummary = plan as OwnedServiceSummary;

        offeringDetail = _offeringBLL.GetById(serviceSummary.OfferingID);

    // For the other types of summary will be 0
    var providerId = offeringDetail.ProviderID;

    offeredPlans .Add(new Tuple<int, string>(providerId, plan.Name));

Once you've gotten your code into a ILookup you can just call Item property (which in C# is called with [...]) to get all values with a given key. So the Check can be entirely replaced by using the ILookup like this:

ILookup<int, string> plansLookup = ...
IEnumerable<string> plansForProvider = plansLookup[providerId]; // Finds all plans for this provider

However, it's not clear that you need to be creating the List<Tuple<int, string>> in the first place. You can just use Linq to generate your ILookup from scratch:

var plansLookup = 
    (from plan in plans
     let productSummary = plan as OwnedProductSummary
     let serviceSummary = plan as OwnedServiceSummary
     let offeringDetail =
         (productSummary != null) ? _offeringBLL.GetById(productSummary.OfferingID) :
         (serviceSummary != null) ? _offeringBLL.GetById(serviceSummary.OfferingID) :
         new OfferingDetail()
     select new 
    .ToLookup(x => x.ProviderId, x => x.Name);
  • \$\begingroup\$ Yes, I pasted the code before checking it as I thought it was relevant. But you're completely right I can create it from scratch \$\endgroup\$ – mitomed Apr 19 '13 at 22:24
  • \$\begingroup\$ Maybe I talked too early in the last comment, I think in this case either it's not possible or it would be a very convoluted expression, right? \$\endgroup\$ – mitomed Apr 19 '13 at 22:35
  • \$\begingroup\$ @mitomed Nah, it's not that bad. See my updated answer. \$\endgroup\$ – p.s.w.g Apr 19 '13 at 22:41
  • \$\begingroup\$ Agreed, apart from a small typo (for instead of from) it works perfectly fine and it's not as terrible as I imagined (fear I had as never got into queries using lets). Thanks very much, I really think you've improved the code a lot \$\endgroup\$ – mitomed Apr 19 '13 at 22:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.