2011-08-16 12 views
6

Chciałbym używać wyliczeń w moich dynamicznych kwerend LINQ.Jak używać wyładowań z Dynamic Linq?

Czy to możliwe, a jeśli?

Rozważmy kod poniżej:

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 
    } 
} 
+0

Czy trzeba używać dynamicznego LINQ. Można to zrobić za pomocą standardowego linq –

+0

@Dean:) Potrzebuję dynamicznego linq. – serhio

Odpowiedz

4

to działa:

houses.AsQueryable<House>() 
    .Where("MainRoom.Type = ConsoleApplication2.RoomType.Kitchen") 
+0

Pierwsza nie działa. "int" nie występuje jako właściwość "House" ..., druga nie działa z tego samego powodu ... i ogólnie nie można użyć "==", ale "=". Obawiam się, że nie przetestowałeś twojego zapytania ... – serhio

+0

Przepraszam - masz rację - napisałem obie opcje z mglistej pamięci ... Właśnie przetestowałem oba i pierwszy był bez wyjścia, ale drugi z pojedynczym znakiem równości działa dobrze, więc zaktualizowałem swoją odpowiedź, aby uwzględnić tylko tę. –

+0

masz powód. Twoje zapytanie działa, więc być może jest to dobra odpowiedź. Jednak już napisałem na innym :), więc zastanawiam się też, jak to działa http://stackoverflow.com/q/7077056/185593 – serhio

1

To powinno działać

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

Dlaczego musisz dynamicznej LINQ w tym przypadku? Jakiej mocy wyjściowej oczekujesz?

Do moich preferencji należy unikać stosowania łańcucha podatnego na błędy. Jeśli zmienisz nazwę klasy lub usługi, nie będziesz w stanie znaleźć błędu, dopóki go nie spotkasz.

Raczej używając wyrażenia

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); 

Można utworzyć wyrażenie gdzie Ty decydujesz, które ciąg filtr ma być używany. Lepiej stwórz klasę statyczną lub może być instrukcją switch, która daje inny typ wyrażenia, którego możesz użyć jako argumentu where.

+0

Łącze statyczne nie ma mowy ... Potrzebuję dynamicznego linq, ponieważ dynamicznie buduję filtr na podstawie specyfikacji filtra użytkownika. – serhio

+0

Nie widzę powodu, dla którego nie można wykonywać typów zapytań, które robisz przy użyciu standardowego linq, od użytkownika. –

+0

@Andrew, jeśli użytkownik wybierze z combo "Kuchnia", muszę przekształcić go w "RoomType.Kitchen", i może to wybierze nie typ pokoju, ale powierzchnia pokoju będzie mniejsza niż powiedzmy 30m2 ... więc ja potrzebujesz zapytania * dynamicznego * – serhio

16

I napotkał ten sam problem i próbował wyraźną odpowiedź określoną przez @Steve Wilkes ale to nie działa dla mnie !! Następnie odkryłem, że dynamiczny LINQ ma dokumentację HTML w tym samym pakiecie, który wspomniał, że wyliczenia mogą być określone jako Literały łańcuchowe.

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

Który pracował dla mnie.

+2

Dzięki! Żadna z powyższych nie zadziałała, ale używa nazwy wartości wyliczeniowej, ponieważ literał działa świetnie. –

+0

To działa idealnie ze mną, świetna porada –

+1

To powinna być zaakceptowana odpowiedź – victorvartan

-1

Aby dodać nowy typ Enum do dynamicznej LINQ, należy dodać następujący kod:

typeof(Enum), 
typeof(T) 

T : Enum type 

w predefinedTypes dynamicznego to praca dla mnie;

1

dodatkowo jeszcze inny parametr użycie wariant

var aRoomsHouses = houses.AsQueryable<House>().Where("MainRoom.Type = @0",RoomType.Kitchen);