2009-06-18 11 views
5

A może jest lepszy sposób.Czy mogę przekazać w T.Property? Pomysły na ulepszenie tej metody?

Buduję dynamiczny generator zapytań dla NHibernate, nie chcemy umieszczać HQL bezpośrednio w aplikacji, chcemy, aby był jak najbardziej agnostyczny. Wygląda to obecnie:

public override IEnumerable<T> SelectQuery(Dictionary<string, string> dictionary) 
    { 
     string t = Convert.ToString(typeof (T).Name); 
     string criteria = string.Empty; 
     foreach (KeyValuePair<string, string> item in dictionary) 
     { 
      if (criteria != string.Empty) 
        criteria += " and "; 


      criteria += item.Key + " = '" + item.Value + "'"; 
     } 

     string query = " from " + t; 

     if (criteria != string.Empty) 
      query += " where " + criteria; 

     return FindByHql(query); 
    } 

ok, super, jednak .... istnieją dwie rzeczy tutaj, które stwarzają problem:

  1. Ta kwerenda zajmuje się tylko „i” mój początkowy myślą jest zbudować metodę dynamicznego budowania słownika, który przyjmuje nazwę właściwości, wartość i operatora "i" lub "lub" i buduje słownik wraz z szeregiem operatorów. Czy to brzmi jak właściwa rzecz?

  2. OK, to działa GREAT, ale gdy jest liczba całkowita, to zawodzi z powodu pojedynczych cudzysłowów. To, co myślę, że będzie NAJLEPSZĄ drogę, to że słownik zaakceptuje <T.Property, string>, a następnie przejdzie do T.Property, aby znaleźć typ danych i odpowiednio się zachowywać. Czy to komplikuję?

Dziękuję.

Odpowiedz

3

Co powiesz na coś takiego.

Gdzie masz wyliczenie do operacji. Zamiast podawać ciąg znaków dla słownika, przekazujesz typ QueryObject, który ma typ wartości i operację dla wartości. Możesz zobaczyć poniżej.

public enum Operation 
{ 
    And, 
    Or 
} 

public class QueryObject 
{ 
    public string Value { get; set; } 
    public Type Type { get; set; } 
    public Operation Operation { get; set; } 
} 

public override IEnumerable<T> SelectQuery(Dictionary<string, QueryObject> dictionary) 
{ 
    string t = Convert.ToString(typeof(T).Name); 
    string criteria = string.Empty; 
    foreach (KeyValuePair<string, QueryObject> item in dictionary) 
    { 
     if (!string.IsNullOrEmpty(criteria)) 
     { 
      switch (item.Value.Operation) 
      { 
       case Operation.And: 
        criteria += " and "; 
        break; 
       case Operation.Or: 
        criteria += " or "; 
        break; 
       default: 
        break; 
      } 
     } 

     if (item.Value.Type == typeof(int)) 
     { 
      criteria += item.Key + " = " + item.Value + " ";  
     } 
     else 
     { 
      criteria += item.Key + " = '" + item.Value + "'"; 
     } 
    } 

    string query = " from " + t; 

    if (criteria != string.Empty) 
     query += " where " + criteria; 

    return FindByHql(query); 
} 
+0

Kiedyś to chyba ja zniósł Słownika wszystko razem i po prostu dodaje „obiekt” jako ciąg do klasy QueryObject. Dzięki! –

1

Proponuję ewentualnie tworząc klasę, która posiada wszystkie właściwości potrzebne:

Name, 
Value, 
Type, 
JoinType (possibly an enum with Or/And) 

wtedy mieć swój sposób wziąć zbiór tych typów, w przeciwieństwie do słownika. W ten sposób możesz łatwo sprawdzić, czy musisz zrobić i/lub, a także sprawdzić, czy potrzebujesz wycen ...

1

Moja podstawowa myśl polega na tym, że stworzenie czegoś takiego nie jest zbyt rozsądne. Piszemy kod generujący HQL. Który z kolei zostaje przekazany do nhibernate, który generuje SQL.

Proponuję rzucić okiem na zapytania NHibernate criteria. Po pierwsze jako łatwiejszy sposób dynamicznego budowania kwerendy NHibernate. Ale także dać wyobrażenie o tym, jak skomplikowane jest toczenie własnego dynamicznego kreatora zapytań.

To powiedziawszy. Gdybym to robił, prawdopodobnie użyłbym NHibernate Criteria jako bazy dla dowolnego dynamicznego konstruktora zapytań. Nie ma powodu, dla którego nie mógłby wygenerować zapytania do użycia przez inną ORM.

Bardziej ogólnym rozwiązaniem problemu jest wykreślenie dostępu do danych, aby móc przełączać ORM, wystarczy zmienić kod pod swoją abstrakcją. To oczywiście więcej pracy, ale nie jestem przekonany, że utrzymywanie kodu dostępu do danych ORM jest czymś szczególnie ważnym.

+0

Zapytania o kryteria to dobry sposób na odejście, ale zostałem z obecną konfiguracją w duchu "zrobienia s ** t done" –

0

Cóż, alternatywą dla tego, co robisz, jest przekazanie Wyrażenie> zamiast słownika, a następnie zanalizowanie wyrażenia Linq dla tego, co chcesz. Niewielką sugestią, którą chciałbym wykonać, jest użycie zapytania Kryterium zamiast HQL. Oczywiście analiza wyrażenia Linq jest prawdopodobnie bardziej skomplikowana niż tutaj.

Być może będziesz w stanie przetworzyć słownik i stworzyć świetny HQL, ale boli mnie głowa, myśląc o zrobieniu tego w ten sposób. Zapytania dotyczące kryteriów wydają się być zaprojektowane do tego typu rzeczy.

Powiązane problemy