How to use Enums with Dynamic Linq?
Asked Answered
C

5

9

I would like to use enumerations in my dynamic LINQ queries.

Is it possible, and if, how?

Consider the code bellow:

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

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            Room aRoom = new Room() { Name = "a Room" };
            Room bRoom = new Room() { Name = "b Room" };
            Room cRoom = new Room() { Name = "c Room" };

            House myHouse = new House
            {
                Rooms = new List<Room>(new Room[] { aRoom }),
                MainRoom = aRoom
            };
            House yourHouse = new House()
            {
                Rooms = new List<Room>(new Room[] { bRoom, cRoom }),
                MainRoom = bRoom
            };
            House donaldsHouse = new House()
            {
                Rooms = new List<Room>(new Room[] { aRoom, bRoom, cRoom }),
                MainRoom = aRoom
            };

            var houses = new List<House>(new House[] { myHouse, yourHouse, donaldsHouse });

            // MainRoom.Name = \"a Room\" and Rooms.Count = 3 or 
            // ?????????????????????????
            var aRoomsHouses = houses.AsQueryable<House>().Where("MainRoom.Type = \"RoomType.Kitchen\"");

            Console.WriteLine("aRoomsHouses count = {0}", aRoomsHouses.Count());
            Console.ReadKey();
        }
    }

    public class House
    {
        public string Address { get; set; }
        public double Area { get; set; }
        public Room MainRoom { get; set; }
        public List<Room> Rooms { get; set; }
    }

    public class Room
    {
        public double Area { get; set; }
        public string Name { get; set; }
        public RoomType Type { get; set; }
    }

    public enum RoomType
    {
        Kitchen,
        Bedroom,
        Library,
        Office
    }
}
Compagnie answered 16/8, 2011 at 9:0 Comment(2)
Do you need to use dynamic-linq. It can be done with standard linqHertzog
@Dean: ) I need dynamic linq.Compagnie
T
4

This works:

houses.AsQueryable<House>()
    .Where("MainRoom.Type = ConsoleApplication2.RoomType.Kitchen")
Troxler answered 16/8, 2011 at 10:29 Comment(6)
first one does not work. 'int' not found as the 'House' property..., the second one not work because of the same reason..., and in general, you can't use "==", but "=". I am afraid you haven't tested your query...Compagnie
Apologies - you're quite right - I wrote both options from hazy memory... I've just tested both and the first was a no-go, but the second with a single equals sign works just fine, so I've updated my answer to only include that one.Troxler
you have reason. Your query works, so, perhaps this is a good answer. However, I already posted on other one :), so also wondering how to make it work https://mcmap.net/q/1170873/-dynamic-expression-using-linq-how-to-find-the-kitchens/185593Compagnie
I've answered that other one, too :)Troxler
Can you try modifying this enum and see if above expression gives proper result? New enum : public enum RoomType { Bedroom, Kitchen, // kitchen moved to second position Library, Office }Extravagance
Yep, changing the order doesn't look to make any difference. Obviously this isn't refactor-friendly, but I don't think @Compagnie is going to be writing the enum values directly in as strings like this - the main thrust of the answer is that the reference to the enum works fine so long as it's fully-qualified.Troxler
S
21

I encountered this same issue and tried the marked answer specified by @Steve Wilkes but it didn't work for me !! Then I discovered that dynamic LINQ has an HTML documentation in the same package which mentioned that Enums can be specified as String Literals.

houses.AsQueryable<House>().Where("MainRoom.Type = \"Kitchen\"")

Which worked for me.

Stratopause answered 21/6, 2012 at 8:57 Comment(1)
Thanks! None of the above worked but using enum value name as literal works great.Shiverick
T
4

This works:

houses.AsQueryable<House>()
    .Where("MainRoom.Type = ConsoleApplication2.RoomType.Kitchen")
Troxler answered 16/8, 2011 at 10:29 Comment(6)
first one does not work. 'int' not found as the 'House' property..., the second one not work because of the same reason..., and in general, you can't use "==", but "=". I am afraid you haven't tested your query...Compagnie
Apologies - you're quite right - I wrote both options from hazy memory... I've just tested both and the first was a no-go, but the second with a single equals sign works just fine, so I've updated my answer to only include that one.Troxler
you have reason. Your query works, so, perhaps this is a good answer. However, I already posted on other one :), so also wondering how to make it work https://mcmap.net/q/1170873/-dynamic-expression-using-linq-how-to-find-the-kitchens/185593Compagnie
I've answered that other one, too :)Troxler
Can you try modifying this enum and see if above expression gives proper result? New enum : public enum RoomType { Bedroom, Kitchen, // kitchen moved to second position Library, Office }Extravagance
Yep, changing the order doesn't look to make any difference. Obviously this isn't refactor-friendly, but I don't think @Compagnie is going to be writing the enum values directly in as strings like this - the main thrust of the answer is that the reference to the enum works fine so long as it's fully-qualified.Troxler
V
1

in addition yet another variant use parameter

var aRoomsHouses = houses.AsQueryable<House>().Where("MainRoom.Type = @0",RoomType.Kitchen);
Vespine answered 7/11, 2013 at 13:59 Comment(0)
E
0

This should work

houses.AsQueryable<House>().Where(rs=>rs.MainRoom.Type == RoomType.Kitchen);

Why do you need dynamic linq in this case? What output you expect

To my preference, use of error prone string should be avoided. If your class or property name changed, you won't be able to find the error until you encounter it.

Rather use expression

    Expression<Func<House, bool>> 
        filter = (p) => p.MainRoom.Type == RoomType.Kitchen; 
        filter = (p) => p.MainRoom.Area > 200;
        filter = (p) => p.Rooms.Sum(rs => rs.Area) > 500;
        filter = (p) => p.Address.Contains("abc");
        filter = (p) => p.Area > 200;
        ...
    var aRoomsHouses = houses.AsQueryable<House>().Where(filter);

You can create the expression where you decide which string filter to be used. Better create a static class or may be switch statement which gives you different type of expression which you can use as where argument.

Extravagance answered 16/8, 2011 at 10:23 Comment(12)
Static link no way... I need dynamic linq, because i build dynamically the filter based on the user filter specification.Compagnie
I see no reason you can't do the types of queries you are doing with standard linq, from user input.Hooch
@Andrew, if user select from the combo "Kitchen", I need to transform it into "RoomType.Kitchen", and maybe it selects not type of the room, but the rooms area be less than say 30m2... so I need a dynamic queryCompagnie
You are getting stuck on the word "dynamic". You can do that sort of query with standard linqHooch
@serhio: Actually the Dynamic Query extension is primarily intended for when the result type varies (output columns, grouping, etc.). If you only need to change the filter then it's better (way faster) to use Predicate Builder. That said, this answer did obviously miss the point of the question.Cavalry
@serhio, you can pass action into where method, you can write you method to build expression which can be used in filter methodExtravagance
Something like this - public List<House> Filter(Expression<Func<MainRoom, bool>> filter) { return houses.AsQueryable<House>()(filter).ToList(); }Extravagance
@Andrew Barber: As I can't predict user input, I can't use static LINQ. The user selects the properties to filter, not me.Compagnie
@Extravagance see this question to understand why static query is not possible in my case: https://mcmap.net/q/1170874/-implement-a-properties-filter-in-net/185593Compagnie
@Compagnie : you are badly misunderstanding the nature of things here. I do queries much more complex than this all the time using predicate builder - standard linq operators.Hooch
@serhio, i understand user will select roomtype & kitchen from drop down or select area and enter > 200 , something like that, based on user input you will build string expression (i dont think u will ask user to enter "MainRoom.Type = ConsoleApplication2.RoomType.Kitchen"). The point where u r building filter string, you can build expression too.Extravagance
@Andrew Barber: Using predicate builder you always have switches for each case a part, in other words, you hardcode each property, and it became impossible to add new properties without switch code changes.Compagnie
I
-1

To add a new Enum type to dynamic linq, you must add the following code :

typeof(Enum),
typeof(T)

T : Enum type

in predefinedTypes of dynamic That's work for me;

Impute answered 22/3, 2013 at 13:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.