7

Is it possible to include or exclude column within linq Select?

var numberOfYears = Common.Tool.NumberOfYear;
 var list = users.Select(item => new
        {
            Id = item.Id,
            Name= item.Name,
            City= Item.Address.City.Name,
            STATUS = Item.Status,
            if(numberOfYears == 1)
            {
               Y1 = item.Records.Y1,
            }
            if(numberOfYears == 2)
            {
               Y1 = item.Records.Y1,
               Y2 = item.Records.Y2,
            }
            if(numberOfYears == 3)
            {
               Y1 = item.Records.Y1,
               Y2 = item.Records.Y2,
               Y3 = item.Records.Y3,
            }
        }).ToList();
    }

The idea is that i want to display Y1,Y2,Y3 only if has values

Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
Maro
  • 2,579
  • 9
  • 42
  • 79
  • 1
    You can just use ternary operator for each property. Resulting objects have to be the same, so each will have to have the 3 `Yx` properties. Just use some default or `null` value for them. – kiziu Sep 13 '16 at 14:52
  • It is possible if you don't mind using [Dynamic Linq](http://stackoverflow.com/questions/16516971/linq-dynamic-select) – Scott Perham Sep 13 '16 at 14:55
  • How are you going to consume the `list` variable? – Yacoub Massad Sep 13 '16 at 14:57
  • 2
    Why not use .Where(x => ...) ? – Austin T French Sep 13 '16 at 14:58
  • There is no link between user input which is number of years and the model. it's basically getting history and user can select the period. maybe the design is bad, but it's not up to me to change that, so i have to take it as it is. – Maro Sep 13 '16 at 21:00

3 Answers3

5

Thanks to the beauty of the dynamic keyword what you need is now possible in C#. Below an example:

public class MyItem
{
    public string Name { get; set; }
    public int Id { get; set; }
}

static void Main(string[] args)
{
    List<MyItem> items = new List<MyItem>
    {
        new MyItem
        {
            Name ="A",
            Id = 1,
        },
        new MyItem
        {
            Name = "B",
            Id = 2,
        }
    };

    var dynamicItems = items.Select(x => {
        dynamic myValue;
        if (x.Id % 2 == 0)
            myValue = new { Name = x.Name };
        else
            myValue = new { Name = x.Name, Id = x.Id };

        return myValue;
    }).ToList();
}

This will return a list of dynamic objects. One with 1 property and one with 2 properties.

PiotrWolkowski
  • 8,408
  • 6
  • 48
  • 68
1

Try this approach:

var numberOfYears = Common.Tool.NumberOfYear;
var list = users.Select(item => new
    {
        Id = item.Id,
        Name = item.Name,
        City = Item.Address.City.Name,
        STATUS = Item.Status,
        Y1 = numberOfYears > 0 ? item.Records.Y1 : 0,
        Y2 = numberOfYears > 1 ? item.Records.Y2 : 0,
        Y3 = numberOfYears > 2 ? item.Records.Y3 : 0
    }).ToList();

Instead of 0, add your default value or null.

Update: According to your comments, the only option for you is to go dynamic. Here's example with dynamics:

var numberOfYears = 3;
var list = users.Select(x =>
{
    dynamic item = new ExpandoObject();
    item.Id = x.Id;
    item.Name = x.Name;
    item.Status = x.Status;

    var p = item as IDictionary<string, object>;
    var recordsType = x.Records.GetType();
    for (var i = 1; i <= numberOfYears; ++i)
        p["Y" + i] = recordsType.GetProperty("Y" + i).GetValue(x.Records);

    return item;
}).ToList();
rpeshkov
  • 4,877
  • 3
  • 27
  • 43
  • This solution will display the column even if they input is 0. the idea is that if the input of numberOfYears = 0 then no column should be displayed. – Maro Sep 13 '16 at 18:00
  • Also number of years can go upto 12 , – Maro Sep 13 '16 at 18:01
0

You can use the ExpandoObject like this:

var data = providers.Select(provider =>
{
    dynamic excelRow = new ExpandoObject();

    excelRow.FirstName = provider.FirstName ?? "";
    excelRow.MiddleName = provider.MiddleName ?? "";
    excelRow.LastName = provider.LastName ?? "";
    
    // Conditionally add columns to the object...
    if (someCondition)
    {
        excelRow.Property1ForCondition = provider.Property1ForCondition;
        excelRow.Property2ForCondition = provider.Property2ForCondition;
    }

    excelRow.DueDate = provider.DueDate ?? null;

    .
    .
    .

    return excelRow;
});

Another variation of the above code can be:

var data = new List<ExpandoObject>();

providers.ForEach(provider =>
{
    dynamic excelRow = new ExpandoObject();

    excelRow.FirstName = provider.FirstName ?? "";
    excelRow.MiddleName = provider.MiddleName ?? "";
    excelRow.LastName = provider.LastName ?? "";
    
    // Conditionally add columns to the object...
    if (someCondition)
    {
        excelRow.Property1ForCondition = provider.Property1ForCondition;
        excelRow.Property2ForCondition = provider.Property2ForCondition;
    }

    excelRow.DueDate = provider.DueDate ?? null;

    .
    .
    .

    data.Add(excelRow);
});
Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480