Simplifying a lambda expression that uses the same code multiple times

.net-core c# entity-framework-core

Question

Is there a way I could simplify my lambda expression:

models = _context.something
    .Where(i => i.Amount > 0)
    .Select(o => new somemodel
    {
        one = (o.property.prices.Where(i => i.IsCurrent == true).FirstOrDefault().Value - o.property.prices.Where(i => i.IsCurrent == true).FirstOrDefault().Price).ToString(),
        two = o.property.prices.Where(i => i.IsCurrent == true).FirstOrDefault().Price,
        three = o.property.prices.Where(i => i.IsCurrent == true).FirstOrDefault().Price.ToPriceStr("£"),
        four = o.property.rents.Where(i => i.IsCurrent == true).FirstOrDefault().Rent * 1200 / o.property.prices.Where(i => i.IsCurrent == true).FirstOrDefault().Price,
        five = Convert.ToInt64(o.property.prices.Where(o => o.IsCurrent == true).FirstOrDefault().Value) * o.property.amount,
        six = (Convert.ToInt64(o.property.prices.Where(o => o.IsCurrent == true).FirstOrDefault().Value) * o.property.amount).ToPriceStr("£"),
    })
    .Distinct()
    .ToList();

This is just a sample the real one used the same sort of code many times. It is really prone to error as if I change it I have so many places to do it.

the code o.property.prices.Where(i => i.IsCurrent == true).FirstOrDefault() is all over my expression. Is there a way I can write in once and reuse it.

1
2
4/6/2020 10:33:59 AM

Accepted Answer

This is where query expression comes in handy, because it allows let clauses.

models = (from o in _context.something
    where o.Amount > 0
    let firstCurrentPrice = o.property.prices.Where(i => i.IsCurrent).FirstOrDefault()
    select new some model 
    {
        one = (firstCurrentPrice.Value - firstCurrentPrice.Price).ToString(),
        two = firstCurrentPrice.Price,
        three = firstCurrentPrice.Price.ToPriceStr("£"),
        four = o.property.rents.Where(i => i.IsCurrent == true).FirstOrDefault().Rent * 1200 / firstCurrentPrice.Price,
        five = Convert.ToInt64(firstCurrentPrice.Value) * o.property.amount,
        six = (Convert.ToInt64(firstCurrentPrice.Value) * o.property.amount).ToPriceStr("£"),
    })
    .Distinct()
    .ToList();
3
4/6/2020 10:39:46 AM

Popular Answer

My suggestion is that you add 'helper' methods to your main class e.g. GetCurrentRent(), GetCurrentPrice(), where you encapsulate the .Where(i => i.Iscurrent).FirstOrDefault() logic. Then in your Select statement you just call these helper methods. This will drastically cleanup that code as well as keeping your 'logic' encapsulated in the class.

models = _context.something
    .Where(i => i.Amount > 0)
    .Select(o => new somemodel
    {
        one = (o.property.GetCurrentPrice().Value - o.property.GetCurrentPrice().Value.Price).ToString(),
        two = o.property.GetCurrentPrice().Value.Price,
        three = o.property.GetCurrentPrice().Value.Price.ToPriceStr("£"),
        four = o.property.GetCurrentRent().Rent * 1200 / o.property.GetCurrentRent().Price,
        five = Convert.ToInt64(o.property.GetCurrentPrice().Value) * o.property.amount,
        six = (Convert.ToInt64(o.property.GetCurrentPrice().Value) * o.property.amount).ToPriceStr("£"),
    })
    .Distinct()
    .ToList();

you can then take it one step further and only select the current Price and Rent as a 'tuple', and then run your logic over that:




models = _context.something
    .Where(i => i.Amount > 0)
    .Select(x => new { Amount = x.amount, CurrentPrice = x.GetCurrentPrice(), CurrentRent = x.GetCurrentRent() })
    .Select(o => new somemodel
    {
        one = (o.CurrentPrice.Value - o.CurrentPrice.Value.Price).ToString(),
        two = o.CurrentPrice.Value.Price,
        three = o.CurrentPrice.Value.Price.ToPriceStr("£"),
        four = o.CurrentRent.Rent * 1200 / o.CurrentRent.Price,
        five = Convert.ToInt64(o.CurrentPrice.Value) * o.Amount,
        six = (Convert.ToInt64(o.CurrentPrice.Value) * o.Amount).ToPriceStr("£"),
    })
    .Distinct()
    .ToList();


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow