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
    }
}
serhio
  • 28,010
  • 62
  • 221
  • 374

5 Answers5

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.

Mohammad
  • 1,930
  • 1
  • 21
  • 31
4

This works:

houses.AsQueryable<House>()
    .Where("MainRoom.Type = ConsoleApplication2.RoomType.Kitchen")
Steve Wilkes
  • 7,085
  • 3
  • 29
  • 32
  • 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... – serhio Aug 16 '11 at 10:39
  • 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. – Steve Wilkes Aug 16 '11 at 10:55
  • 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 http://stackoverflow.com/q/7077056/185593 – serhio Aug 16 '11 at 11:01
  • I've answered that other one, too :) – Steve Wilkes Aug 16 '11 at 11:15
  • 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 } – hungryMind Aug 16 '11 at 12:34
  • Yep, changing the order doesn't look to make any difference. Obviously this isn't refactor-friendly, but I don't think @serhio 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. – Steve Wilkes Aug 16 '11 at 12:51
1

in addition yet another variant use parameter

var aRoomsHouses = houses.AsQueryable<House>().Where("MainRoom.Type = @0",RoomType.Kitchen);
Grundy
  • 13,356
  • 3
  • 35
  • 55
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.

hungryMind
  • 6,931
  • 4
  • 29
  • 45
  • Static link no way... I need dynamic linq, because i build dynamically the filter based on the user filter specification. – serhio Aug 16 '11 at 10:38
  • I see no reason you can't do the types of queries you are doing with standard linq, from user input. – Andrew Barber Aug 16 '11 at 10:59
  • @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* query – serhio Aug 16 '11 at 11:04
  • You are getting stuck on the word "dynamic". You can do that sort of query with standard linq – Andrew Barber Aug 16 '11 at 11:06
  • @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. – Aaronaught Aug 16 '11 at 12:10
  • @serhio, you can pass action into where method, you can write you method to build expression which can be used in filter method – hungryMind Aug 16 '11 at 12:25
  • Something like this - public List Filter(Expression> filter) { return houses.AsQueryable()(filter).ToList(); } – hungryMind Aug 16 '11 at 12:31
  • @Andrew Barber: As I can't predict user input, I can't use static LINQ. The user selects the properties to filter, not me. – serhio Aug 16 '11 at 15:12
  • @hungryMind see this question to understand why static query is not possible in my case: http://stackoverflow.com/q/7026855/185593 – serhio Aug 16 '11 at 15:13
  • @serhio : 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. – Andrew Barber Aug 16 '11 at 15:14
  • @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. – hungryMind Aug 16 '11 at 16:50
  • 1
    @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. – serhio Aug 17 '11 at 08:38
-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;

kleopatra
  • 51,061
  • 28
  • 99
  • 211
Amine
  • 43
  • 1
  • 1