2013-05-09 19 views
5

Zastanawiam się, czy ORMLite ma rozwiązanie QueryMultiple, takie jak eleganckie.Servicestack ORMLite Query Multiple

Mój przypadek użycia służy do uzyskiwania wyników stronicowanych.

return new { 
    Posts = conn.Select<Post>(q => q.Where(p => p.Tag == "Chris").Limit(20, 10)) 
    TotalPosts = conn.Count<Post>(q.Where(p => p.Tag == "Chris")) 
}; 

Mam też kilka innych przypadków, w których jestem liczące kilka innych statystyk oprócz głównego zapytania i jestem pragnie uniknąć wielokrotnych roundtrips.

(Prawdopodobnie niepowiązane, ale używam PostgreSQL)

+0

Czy znaleźć rozwiązanie dla tego? – kaptan

Odpowiedz

4

Prawdopodobnie można zrobić coś takiego:

var bothThings = db.Exec(cmd => { 

    cmd.CommandText = @" 
     select * from TableA 
     select * from TableB"; 

    var both = new BothAandB(); 

    using (var reader = cmd.ExecuteReader()) 
    { 
     both.a = reader.ConvertToList<A>(); 
     reader.NextResult(); 
     both.b = reader.ConvertToList<B>(); 
    } 

    return both; 

}); 

To może być możliwe, aby owinąć to w metodę rozszerzenia, ale nic mądry przychodzi mi na myśl.

+1

To nie zadziała w obecnej implementacji. 'ConvertToList' stosuje wewnętrznie' using (reader) ', który zamyka czytnik po utylizacji, uniemożliwiając dostęp do funkcji' NextResult() '. –

3

Możesz łatwo stworzyć kilka pomocniczych rozszerzeń OrmLite (działa w wersji 3.9.55.0), które NIE otoczyją czytnika. Jest to dość łatwe, ponieważ metody, których potrzebujesz, są publiczne. Oto jak to zrobiłem.

public static class MultiResultReaderOrmLiteExtensions 
{ 
    public static IList CustomConvertToList<T>(this IDataReader dataReader) 
    { 
     var modelDef = ModelDefinition<T>.Definition; 
     var type = typeof (T); 
     var fieldDefs = modelDef.AllFieldDefinitionsArray; 
     var listInstance = typeof(List<>).MakeGenericType(type).CreateInstance(); 
     var to = (IList)listInstance; 
     var indexCache = dataReader.GetIndexFieldsCache(modelDef); 
     while (dataReader.Read()) 
     { 
      var row = type.CreateInstance(); 
      row.PopulateWithSqlReader(dataReader, fieldDefs, indexCache); 
      to.Add(row); 
     } 
     return to; 
    } 

    public static Dictionary<string, int> GetIndexFieldsCache(this IDataReader reader, 
     ModelDefinition modelDefinition = null) 
    { 
     var cache = new Dictionary<string, int>(); 
     if (modelDefinition != null) 
     { 
      foreach (var field in modelDefinition.IgnoredFieldDefinitions) 
      { 
       cache[field.FieldName] = -1; 
      } 
     } 
     for (var i = 0; i < reader.FieldCount; i++) 
     { 
      cache[reader.GetName(i)] = i; 
     } 
     return cache; 
    } 
} 

Następnie można nazwać jak coś takiego:

using (var db = _connectionFactory.OpenDbConnection()) 
{ 
    var cmd = db.api_GetSprocWithMultResults(id); 
    using (IDataReader reader = cmd.DbCommand.ExecuteReader()) 
    { 
     meta = reader.CustomConvertToList<Element_Media_Meta>().Cast<Element_Media_Meta>().ToList(); 
     reader.NextResult(); 
     queues = reader.CustomConvertToList<Element_Media_ProcessQueue>().Cast<Element_Media_ProcessQueue>().ToList(); 

    } 
}