views:

31

answers:

1

I have a class say

public class CostStore
{
    int DirectorateId { get; set; }

    decimal NewCar { get; set; }

    decimal ContractorNew { get; set; }

    decimal ContractorRenew { get; set; }

    decimal ContractorLost { get; set; }

    decimal ContractorStolen { get; set; }

    decimal InternalNew { get; set; }

    decimal InternalRenew { get; set; }

    decimal InternalLost { get; set; }

    decimal InternalStolen { get; set; }        
}

and in my controller i want to find out say

var c = from p in _service.List().Where (condition) p.InternalNew/InternalRenew

(etc) property based on a session variable like so in the function below, how can I do this in linq statement...any ideas (_service.List() lists the IEnumerable of the class CostStore

private string FindProperty()
{
    switch (Session[Constants.FORMSESSIONKEY].ToString())
    {
        case Constants.NEWAPP:
            return "InternalNew";
        case Constants.LOST:
            return "InternalLost";
        case Constants.NEWCAR:
            return "NewCar";
        case Constants.OTHER:
            return "InternalStolen";
        case Constants.RENEW:
            return "InternalRenew";
        default:
            return String.Empty;  
     }
}

Currently I am having to do this

private Decimal FindProperty()
{
    switch (Session[Constants.FORMSESSIONKEY].ToString())
    {
        case Constants.NEWAPP:
            return (from p in _costStoreService.List().Where(p => p.DirectorateId == _applicant.DirectorateId)
                    select p.InternalNew).Single() ?? 0.0M;
        case Constants.LOST:
            return (from p in _costStoreService.List().Where(p => p.DirectorateId == _applicant.DirectorateId)
                    select p.InternalLost).Single();
        case Constants.NEWCAR:
            return (from p in _costStoreService.List().Where(p => p.DirectorateId == _applicant.DirectorateId)
                    select p.NewCar).Single();
        case Constants.OTHER:
            return (from p in _costStoreService.List().Where(p => p.DirectorateId == _applicant.DirectorateId)
                    select p.InternalStolen).Single();
        case Constants.RENEW:
            return (from p in _costStoreService.List().Where(p => p.DirectorateId == _applicant.DirectorateId)
                    select p.InternalRenew).Single();
        default:
            return 0.0M;
        }
    }

but its a lot of duplicate code, also no check for sequence containing 0 values...

+1  A: 

I'm assuming your service returns IQueryable<T>. You can use an Expression to define projection outside of your query:

    private Expression<Func<CostStore,Decimal>> GetProjection()
    {
        switch (Session[Constants.FORMSESSIONKEY].ToString())
        {
            case Constants.NEWAPP: 
                return c => c.InternalNew;
            case Constants.LOST:
                return c=> c.InternalLost;
            // ... etc, you get the idea
            default:
                return c => 0m; // or some other sensible default
               // break;
        }
    }

If your service returns IEnumerable<T>, use Func<CostStore,decimal> instead.

You can use it like this:

var projection = GetProjection();
var c = _service.List().Where (condition).Select(projection) 

EDIT: put this in a console application, study and learn.

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication13
{
class Program
{
    static void Main(string[] args)
    {
        var _service = new Service();

        Func<CostStore, bool> condition = s => s.DirectorateId == 10;
        Func<CostStore, decimal> projection = GetProjection();

        var c = _service.List().Where(condition).Select(projection);
    }

    private static Func<CostStore, decimal> GetProjection()
    {
        return c => c.NewCar;
    }

    class Service
    {
        public IEnumerable<CostStore> List()
        {
            return new List<CostStore>();
        }
    }

    public class CostStore
    {
        public int DirectorateId { get; set; }
        public decimal NewCar { get; set; }
    }
}
}
jeroenh
There is no need to make it an expression if you are only dealing with an `IEnumerable<T>`.
leppie
What would I add for checking sequence with 0 values ?? 0.0M any ideas...also where is a good place to get used to expressions?? Cheers
@leppie, you're absolutely right, but it is not immediately obvious whether _service.List() returns IQueryable or IEnumerable.
jeroenh
Further it says that a query body must end with select clause or group clause. _service.List() is IEnumerable<T>, would still like to know alternate option.
@jeroenh: A `List<T>` which is always `IEnumerable<T>`. Edit: Sorry, just noted that it is `List()` and not `ToList()`. Bad method name, bad!
leppie
@user182630 the query as written will return an empty `IEnumerable<decimal>` if there are no items returned from _service.List().
jeroenh
from p in _costStoreService.List().Where(p => p.DirectorateId == _applicant.DirectorateId).Select(projection);When I do that it says query must end with a select clause or group clause, if I then change it to(from p in _costStoreService.List().Where(p => p.DirectorateId == _applicant.DirectorateId).Select(projection) select p).Single();it comes out with lots of other errors such as doesnt contains definition of select and cannot convert ienumerable<> to Iqueryable<> , and how do I set the result to 0M should it be empty soemthing like null??0M;
from p in _costStoreService.List().Where(p => p.DirectorateId == _applicant.DirectorateId) select(projection); using this however gives me conversion exception Cannot implicitly convert type 'System.Func<CostStore,decimal>' to 'decimal'
@user182630. It works for me. Don't use the linq syntax but the extension method syntax, so no "from p in ... select" but simply _service.Where(...).Select(...)
jeroenh
If I do that, I get the same error IEnumerable<costStore> doesnt contain definition of Select, cannot convert Tresult to decimalcannot convert Ienumerable<coststore> to Iqueryable<coststore>
@user182630 what is the signature of _service.List() ?
jeroenh
@user182630 see my edited answer for sample code - try it in a Console app
jeroenh
Thanks jero, I wonder why Expression was causing issues despite passing even the .body which should in theory return the same Tresult. Also is there anyway I can check for if sequence contains nothing and set it to some default... I was hoping for a shortcut syntax like ?0M:null