2013-05-09 13 views
5

Mi chiedevo se ORMLite avesse una soluzione QueryMultiple come dapper.Servicestack ORMLite Query Multiple

Il mio caso di utilizzo è ottenere risultati impaginati.

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

Ho anche un paio di altri casi in cui sto calcolando alcune altre statistiche, oltre a una query principale, e sono ansioso di evitare molteplici andata e ritorno.

(Probabilmente non collegati, ma sto usando PostgreSQL)

+0

Hai trovato una soluzione per questo? – kaptan

risposta

4

Probabilmente si può fare qualcosa di simile:

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; 

}); 

Potrebbe essere possibile avvolgere questo in un metodo di estensione, ma niente di intelligente mi viene in mente

+1

Questo in realtà non funzionerà nella sua attuale implementazione. 'ConvertToList' applica un' using (reader) 'internamente che chiude il lettore dopo l'eliminazione, impedendo che' NextResult() 'sia accessibile. –

3

È possibile creare alcune estensioni OrmLite di supporto (funziona in v 3.9.55.0) abbastanza facilmente che NON avvolgono il lettore. È piuttosto facile dato che i metodi di cui hai bisogno sono pubblici. Ecco come l'ho fatto.

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

quindi è possibile chiamare come qualcosa di simile:

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

    } 
}