2009-12-20 8 views
5

Ho qualche metodo da linq a sql e quando fa la query restituisce un tipo anonimo.Come restituire una raccolta di elenchi generica in C#?

Voglio restituire quel tipo anonimo al mio livello di servizio per fare un po 'di logica e cose su di esso.

Non so come restituirlo però.

ho pensato che avrei potuto fare questo

public List<T> thisIsAtest() 
{ 
    return query; 
} 

ma ottengo questo errore

Error 1 The type or namespace name 'T' could not be found (are you missing a using directive or an assembly reference?) 

quindi non so cosa assemblaggio che mi manca o se questo è anche il caso.

Grazie

EDIT

Ok il mio primo problema è stato risolto, ma ora ho un nuovo problema che io non sono sicuro di come risolvere dato che non so molto di tipi anonimi.

ottengo questo errore

Impossibile convertire implicitamente il tipo 'System.Collections.Generic.List' a 'System.Collections.Generic.List

Ecco la query

DbContext.Table.Where(u => u.Table.UserId == userId && u.OutOFF != 0) 
     .GroupBy(u => new { u.Table.Prefix }) 
     .Select(group => new { prefix = group.Key, 
           Marks = group.Sum(item => (item.Mark * item.Weight)/item.OutOFF) }) 
     .ToList(); 

Modifica 2

public class ReturnValue 
{ 
    string prefix { get; set; } 
    decimal? Marks { get; set; } 
} 

public List<ReturnValue> MyTest(Guid userId) 
{ 
    try 
    { 
     var result = dbContext.Table.Where(u => u.Table.UserId == userId && u.OutOFF != 0).GroupBy(u => new { u.Table.Prefix }) 
     .Select(group => new { prefix = group.Key, Marks = group.Sum(item => (item.Mark * item.Weight)/item.OutOFF) }).ToList(); 
     return result; 
    } 
    catch (SqlException) 
    { 
     throw; 
    } 

select ha questo in esso

Anonymous Types: 

a is new{string Prefix} 
b is new{ 'a prefix, decimal? marks} 
+0

perché non puoi semplicemente definire un nuovo tipo 'class ReturnValue {int prefix; segni decimali; } 'e quindi restituisce un' nuovo ReturnValue (....) 'invece di un tipo anonimo ?? –

+0

Avrò bisogno di un esempio. Ho aiutato a fare questa domanda, fa quello che voglio, ma se può essere cambiato o aggiunto qualcosa per renderlo non anonimo, sono tutto per quello. – chobo2

+0

Non stai usando il codice che ho menzionato! In '.Select()', devi usare: '.Select (group => new RETURNVALUE {prefix = group.Key, ...' - questo è * NON * quello che hai! Non hai aggiunto il ** TYPE ** in fase di creazione in .Select() - questo è il tuo problema –

risposta

8

Non si può - periodo. L'utente non può utilizzare tipi anonimi al di fuori del proprio ambito, ad es. non è possibile restituirli come valori di ritorno da un metodo.

Se è necessario restituirli, è necessario definire una nuova classe concreta anziché il tipo anonimo e utilizzarla al posto del tipo anonimo.

di blog post sul scoping di tipi anonimi, e vedere Vedere Rick Strahl la MSDN docs here che chiaramente:

un tipo anonimo ha metodo di portata. Per passare un tipo anonimo, o una raccolta che contiene tipi anonimi , al di fuori del limite di un metodo, è necessario che il primo esegua il cast del tipo su oggetto. Tuttavia, questo sconfigge la forte digitazione del tipo anonimo .Se è necessario memorizzare i risultati della query o passare al di fuori del limite del metodo, prendere in considerazione l'utilizzo di una struttura o classe ordinaria denominata anziché di tipo anonimo .

OK, certo, ci sono sporchi trucchetti per restituire tipi anonimi. Ma se Microsoft MSDN E Jon Skeet scoraggia questa pratica, allora - non farlo semplicemente. Per definizione e l'intenzione, tipi anonimi sono legati al metodo che stanno definiti in

UPDATE per chobo2:. Non so che cosa i vostri tipi di dati sono - solo indovinare - ma assumendo "prefisso" è un int e "segni" è un numero decimale, è possibile definire una nuova classe:

public class ReturnValue 
{ 
    int prefix { get; set; } 
    decimal Marks { get; set; } 
} 

e quindi il codice sarebbe un metodo che restituisce un List<ReturnValue>:

public List<ReturnValue> thisIsAtest() 
{ 
    DbContext.Table.Where(u => u.Table.UserId == userId && u.OutOFF != 0) 
    .GroupBy(u => new { u.Table.Prefix }) 
    .Select(group => new ReturnValue 
          { prefix = group.Key, 
          Marks = group 
           .Sum(item => (item.Mark * item.Weight)/item.OutOFF) }) 
    .ToList(); 
} 

La chiave qui è: nella vostra .Select metodo, invece di creare una nuova istanza di un tipo anonimo:

 .Select(group => new { prefix = group.Key, marks = .... } 

si crea un'istanza di un tipo concreto:

 .Select(group => new ReturnValue { prefix = group.Key, marks = .... } 

In questo modo, avrete una classe concreta ReturnValue - chiama quel qualcosa che ti piace - e poi puoi facilmente restituire un elenco di quel tipo, e usare quel tipo anche altrove.

+0

In realtà, puoi: http://msmvps.com/blogs/jon_skeet/archive/2009/01/09/horrible-grotty-hack-returning-an-anonymous-type-instance.aspx Non che lo consiglierei anche se. –

+0

Hmm posso vedere un esempio. Lo capisco adesso. Non voglio fare la logica nel mio livello di repository, altrimenti ho bisogno di fare 2 degli stessi metodi perché li uso per posizionare ma ho bisogno di usare i dati in 2 modi diversi. Impossibile convertire implicitamente il tipo 'System.Collections.Generic.List ' a 'System.Collections.Generic.List chobo2

+0

@MarkByers: ma Jon stesso dice: "non utilizzare questo codice" .. .... così davvero, a tutti gli effetti: ** NON ** - non provarci nemmeno. –

6
public List<T> thisIsAtest<T>() 
{ 
    return query; 
} 
+0

Che ha risolto il problema ma ora ottengo questo Impossibile convertire implicitamente il tipo 'System.Collections.Generic.List ' a 'Sistema .Collections.Generic.List chobo2

+1

La query che si sta restituendo è un elenco di tipi anonimi, è possibile solo restituire un elenco di . È possibile utilizzare oggetti e il cast di Jon Skeet, ma è fortemente sconsigliato. –

2

Si desidera restituire un tipo anonimo da un metodo normale? Sono abbastanza sicuro che sia possibile con Reflection, ma non ci sarebbe alcun tipo di sicurezza e tutta una serie di altri problemi. Per non dire che sembra strano dal punto di vista dei codici di chiamata. Dovresti sostanzialmente restituire l'oggetto che penso.

È consigliabile utilizzare una classe o una struttura e inserire i valori.

0

I tipi anonimi sono molto limitati, è possibile utilizzarli solo nell'ambito del metodo in cui sono stati dichiarati.

È possibile passarli indietro come oggetti semplici, ma poi si perdono le informazioni sul tipo. Ho visto alcune soluzioni che trasmettono un tipo anonimo; ma usano la riflessione per recuperare le proprietà in un secondo momento.

Problemi correlati