2010-03-28 16 views
6

Przejdź do "konkretnego pytania" w razie potrzeby. Niektóre tła:Jak napisać ten SQL Linq jako kwerendę dynamiczną (używając łańcuchów)?

Scenariusz: Mam zestaw produktów z filtrem "drążenie w dół" (obiekt zapytania) wypełnionym DDL. Każda progresywna selekcja DDL dodatkowo ograniczy listę produktów, a także opcje pozostawione dla DDL. Na przykład wybranie młotka z narzędzi ogranicza rozmiary produktu, pokazując tylko rozmiary młotka.

Obecna konfiguracja: stworzyłem obiekt zapytania, wysłał go do repozytorium, a karmione każdą opcję do SQL „tabeli funkcja ceniony”, gdzie wartości null reprezentowania „dostać wszystkie produkty”.

Uważam to za dobry wysiłek, ale daleko od akceptowalnego DDD. Chcę uniknąć jakiegokolwiek "programowania" w SQL, mam nadzieję, że robię wszystko z repozytorium. Komentarze na ten temat będą mile widziane.

konkretne pytanie:

Jak chciałbym przepisać tej kwerendy jako Dynamic Query? Odsyłacz do czegoś takiego jak 101 Linq Examples byłby fantastyczny, ale z zakresem dynamicznym kwerendy. Naprawdę chcę przekazać tę metodę polu w cudzysłowie "", dla których chcę listę opcji i ile produktów ma tę opcję.

from p in db.Products 
group p by p.ProductSize into g 
select new Category { 
     PropertyType = g.Key, 
     Count = g.Count() } 

Każda z nich będzie miała DLL „Wybór (21)”, w którym przycisk (21) znajduje się ilość produktów, które mają tę cechę. Po wybraniu opcji wszystkie pozostałe pozostałe pliki DDL zostaną zaktualizowane o pozostałe opcje i liczby.

Edycja: Dodatkowe uwagi:

.OrderBy("it.City") // "it" refers to the entire record 
.GroupBy("City", "new(City)") // This produces a unique list of City 
.Select("it.Count()") //This gives a list of counts... getting closer 
.Select("key") // Selects a list of unique City 
.Select("new (key, count() as string)") // +1 to me LOL. key is a row of group 
.GroupBy("new (City, Manufacturer)", "City") // New = list of fields to group by 
.GroupBy("City", "new (Manufacturer, Size)") // Second parameter is a projection 

Product 
.Where("ProductType == @0", "Maps") 
.GroupBy("new(City)", "new (null as string)")// Projection not available later? 
.Select("new (key.City, it.count() as string)")// GroupBy new makes key an object 

Product 
.Where("ProductType == @0", "Maps") 
.GroupBy("new(City)", "new (null as string)")// Projection not available later? 
.Select("new (key.City, it as object)")// the it object is the result of GroupBy 

var a = Product 
     .Where("ProductType == @0", "Maps") 
     .GroupBy("@0", "it", "City") // This fails to group Product at all 
     .Select("new (Key, it as Product)"); // "it" is property cast though 

Czego nauczyłem się tak daleko jest LinqPad jest fantastyczna, ale wciąż szuka odpowiedzi. W końcu, jak sądzę, całkowicie przypadkowe badania, takie jak te, będą dominować. LOL.

Edit:

Jon Skeet miał fantastyczny pomysł: co muszę rzucać jak IGrouping<string, Product>. Dzięki Jon Skeet! Po rzutowaniu obiektu można wyliczyć zbiory i podać wyniki na oddzielnej liście.

+0

Potrzebujesz pełnego zapytania dynamicznego? Czy kryteria filtrowania (klauzula Where) nie są jedynym aspektem dynamicznym? – Gabe

+0

Uważam, że potrzebuję pełnego DQ. Bez duplikowania tego kodu dla każdego pola, które chcą filtrować, będę musiał określić pole GroupBy jako ciąg znaków. –

+0

Przesyłanie do IGrouping jest możliwe tylko wtedy, gdy zwrócisz "it". Kiedy używasz. Wybierz ("nowy (klucz, to jak produkt, count() jako licznik)") jak obsłużyć to ???? –

Odpowiedz

4

Nie jestem pewien, jak to zrobić, używając składni zapytania (jak wyżej), ale używając składni Metody, możemy użyć wyrażenia < Func <, jak pokazano poniżej.Ten przykład działa przeciwko bazie danych AdventureWorks SQL Server (tabela produktów) i pozwala określić kolumnę, która ma być grupowana za pomocą ciągu znaków (w tym przykładzie wybrałem rozmiar)

using System; 
using System.Linq; 
using System.Linq.Expressions; 

namespace LinqResearch 
{ 
    public class Program 
    { 
     [STAThread] 
     static void Main() 
     { 
      string columnToGroupBy = "Size"; 

      // generate the dynamic Expression<Func<Product, string>> 
      ParameterExpression p = Expression.Parameter(typeof(Product), "p"); 

      var selector = Expression.Lambda<Func<Product, string>>(
       Expression.Property(p, columnToGroupBy), 
       p 
      ); 

      using (LinqDataContext dataContext = new LinqDataContext()) 
      { 
       /* using "selector" caluclated above which is automatically 
       compiled when the query runs */ 
       var results = dataContext 
        .Products 
        .GroupBy(selector) 
        .Select((group) => new { 
         Key = group.Key, 
         Count = group.Count() 
        }); 

       foreach(var result in results) 
        Console.WriteLine("{0}: {1}", result.Key, result.Count); 
      } 

      Console.ReadKey(); 
     } 
    } 
} 
1

Po przyjrzeniu się C# Bits autor omawia sposób tworzenia filtrów kaskadowych przy użyciu danych dynamicznych. Nie brzmi to tak, jakbyś korzystał z Danych dynamicznych, ale ma też fajnego kreatora wypowiedzi, który może ci się przydać. Zobacz BuildQueryBody, a następnie poniższą sekcję metod rozszerzeń na Iqueryable.

Ponieważ nie korzystasz z dynamicznych danych, musisz uporać się z brakiem dostępu do obiektu "MetaForeignKeyColumn", ale podejrzewam, że jego podejście może ci pomóc w odpowiedzi na twoje pytanie.

Mam nadzieję, że to pomoże.