0

Using linq, I'm trying to implement the following logic-

Iqueryable.Select(q=> new {
    if a then q.field1,q.field2,q.field3
    else if b then q.field1, q.field4
    else q.field5,q.field6,q.field7,q.field8
});

Any ideas for the best way to do this?

Mike Turner
  • 471
  • 1
  • 7
  • 22
  • 1
    You want to dynamically change the return type of the expression? [This may be the essence of the answer](http://stackoverflow.com/a/15555103/424129), but it'll be a hell of a verbose linq expression by the time you're done. – 15ee8f99-57ff-4f92-890c-b56153 Jul 19 '16 at 20:18
  • You can only do this by returning a dynamic. anonymous types are type-safe. What you are doing is not. I may have some code for you, but it is at work. I dynamically create an anonymous type based on string input. But it is all at work, I have a vacation :) – Michael Jul 19 '16 at 20:23
  • @S.Akbari that doesn't work – Mike Turner Jul 19 '16 at 20:23
  • @Michael sounds nice, would love to see – Mike Turner Jul 19 '16 at 20:24
  • Found something similar [here](http://stackoverflow.com/questions/16516971/linq-dynamic-select). Maybe you somehow can use that. Otherwise, I will try to get back to you when back to work in about two weeks. – Michael Jul 19 '16 at 20:25
  • so far nothing working for me besides just building my query with a long if else.... don't really like it too much. any more professional ideas are welcome – Mike Turner Jul 19 '16 at 20:35
  • If `q` really is the same `q` in every case, have you confirmed that there's no performance hit from returning a class that has all the fields, but simply not initializing the fields you don't care about in any particular case? Why not have a method `Func GetF(a,b,...)` which returns the right `Select` lambda according to your conditions `a`/`b` etc. Then `query.Select(GetF(a,b,c))`. – 15ee8f99-57ff-4f92-890c-b56153 Jul 20 '16 at 13:02

2 Answers2

2

You could certainly encapsulate this into a method that returns dynamic, although you lose your type safety and always with dynamic, a bit of performance.

public dynamic DynamicSelect(Expression<Func<Address, dynamic>> query)
{
    return Addresses.Select(query).Take(1).ToList();
}

You can then call it and retrieve data from it like so:

var result = DynamicSelect(q => new {q.Id, q.AddressLine1});
Console.WriteLine(result[0].Id);

When using DbSets, you can even take this a step further and genericize it:

public dynamic DynamicSelect<TEntity>(Expression<Func<TEntity, dynamic>> query)
{
    return context.DbSet<TEntity>.Select(query).Take(1).ToList();
}

Personally I'd ask yourself if this type of flexibility is really necessary. You're killing your type safety for a marginal increase in "flexibility".

David L
  • 32,885
  • 8
  • 62
  • 93
  • thx, I can't lose any performance, but I do need to keep changing my list of fields. I don't want a long if statement bec I can have lots of conditions - like if a then if nestedCondtion&&secondNestedCondition then.... else if nestedCondition then.... else if b... – Mike Turner Jul 19 '16 at 20:52
  • 1
    @MikeTurner you'd have to measure the impact to ***verify*** if there is a ***demonstrable*** performance hit. I can't assure you that there is or is not. It depends on your situation. But as always with dynamic, it needs to be called out. – David L Jul 19 '16 at 20:53
  • not even sure how this thing would work for me. what I would really love is just something like - if condition -- add fieldOne to select, if conditionTwo - add fieldTwo to select, if conditionThree --- add fieldThree to select etc. – Mike Turner Jul 19 '16 at 20:55
  • like would work great if I can pass a list of propertyInfo into my .Select(q=> listPropInfo) – Mike Turner Jul 19 '16 at 20:57
  • @MikeTurner you can't change the signature of `Select()`...it is what it is. All you can do is work within the context of the method. It requires an expression that takes in a type and returns a new type. So you'd have to work around that. If you can stop needing to use an anonymous type and instead use a concrete type with all the potential fields, this becomes a much easier problem. – David L Jul 19 '16 at 21:02
  • nope. wont work. I guess I can just use system.linq.dynamic and pass a string of my concatenated fields – Mike Turner Jul 19 '16 at 21:16
0

I think you can try something like this

        IQueryable query;  
        if (a)
            query.Select(q=> new {q.field1,q.field2,q.field3});
        else if (b)
            query.Select(q=> new {q.field1, q.field4});
        else
            .Select(q=> new {q.field5,q.field6,q.field7,q.field8});
Jeferson Almeida
  • 144
  • 2
  • 13