HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Tuple/Lookup conundrum

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
lookuptupleconundrum

Problem

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>();
foreach (var plan in plans)
{
    // ....Some code...
    offeredPlans .Add(new Tuple(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 
    }
}


Being

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


Is this terrible or does it make sense?

  • I've never used before these classes (Tuple, Lookup...)



  • 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).



Edit

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

Solution

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 plansLookup = ...
IEnumerable plansForProvider = plansLookup[providerId]; // Finds all plans for this provider


However, it's not clear that you need to be creating the List 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 
     {
         offeringDetail.ProviderID,
         plan.Name
     })
    .ToLookup(x => x.ProviderId, x => x.Name);

Code Snippets

ILookup<int, string> plansLookup = ...
IEnumerable<string> plansForProvider = plansLookup[providerId]; // Finds all plans for this provider
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 
     {
         offeringDetail.ProviderID,
         plan.Name
     })
    .ToLookup(x => x.ProviderId, x => x.Name);

Context

StackExchange Code Review Q#25277, answer score: 2

Revisions (0)

No revisions yet.