2009-07-01 9 views
44

Eventuali duplicati:
LINQ to SQL: Return anonymous type?Come restituire tipo anonimo dal metodo C# che utilizza LINQ to SQL

Ho un LINQ standard per query SQL, che restituisce i dati come un tipo anonimo (contenente circa 6 colonne di dati di vari tipi di dati).

Vorrei rendere questo oggetto restituito disponibile ad altre parti del programma, restituendolo al metodo-chiamante o assegnandolo a una proprietà dell'oggetto contenente il metodo.

Come posso fare questo dato che è un tipo anonimo ("var")?

EDIT - Ecco il codice:

using (ormDataContext context = new ormDataContext(connStr)) 
    { 
     var electionInfo = from t1 in context.elections 
        join t2 in context.election_status 
        on t1.statusID equals t2.statusID 
        select new { t1, t2 }; 
    } 
+0

Quali sono i campi t1, t2? –

+0

Lasciando questo come una traccia di breadcrumb alla domanda originale per ora. Lascia un commento se pensi che le due domande debbano essere unite, e io ricontrollerò più tardi. –

+0

Solo per chiarire, 'var' non è un tipo anonimo. 'var' è una parola chiave abbreviata che puoi usare se il compilatore può dedurre il tipo. In questo caso, 'electionInfo' è il tipo anonimo. –

risposta

65

Effettuare il tipo anonimo in una classe ...

public class Person 
{ 
    public Person() { 
    } 

    public String Name { get; set; } 
    public DateTime DOB { get; set; } 
} 


Person p = 
    from person in db.People 
    where person.Id = 1 
    select new Person { 
     Name = person.Name, 
     DOB = person.DateOfBirth 
    } 
+0

+1 ho appena postato una risposta proprio come questa, mi ha battuto. :) –

+0

lo odio quando ciò accade! :) –

+3

OK, quindi stai praticamente dicendo di non usare la classe anonima ... Sono d'accordo che questo sembra molto più chiaro. Immagino che mi stia chiedendo perché la maggior parte degli esempi LINQ usano var se sono così difficili da lavorare con ... – alchemical

19

Non è possibile digitare qualsiasi metodo in C# per essere il tipo esplicito di un anonimo tipi. Non possono essere "nominati" per così dire e quindi non possono apparire nelle firme dei metadati.

Se davvero si vuole restituire un valore che è un tipo anonimo ci sono 2 opzioni

  1. hanno il tipo di ritorno del metodo sia System.Object. È quindi possibile eseguire hack maliziosi per ottenere un valore digitato in un altro metodo. Questo è molto fragile e non lo consiglio.
  2. Utilizzare un metodo generico e un tipo di trucco di inferenza per ottenere il tipo di reso corretto. Ciò richiederebbe una definizione di firma molto interessante per il tuo approccio.

I tipi anonimi non erano destinati a essere passati in questo modo. Nel punto in cui devi passare tra le tue funzioni in questo modo, è meglio definire un tipo in modo esplicito.

+1

Usa tipo di dati dinamico –

+0

"Nel punto in cui è necessario passarli tra le tue funzioni in questo modo, è meglio definire un tipo in modo esplicito. [ Ovviamente non sei un golfista (JavaScript)] (https://s-media-cache-ak0.pinimg.com/736x/76/a3/9c/76a39cea29fe872eab52a6b4680f5c66.jpg). ; ^) – ruffin

5

Jon Skeet ha scritto un blog su come farlo, che è giustamente intitolato Horribly Grotty Hack. Proprio come suggerisce il titolo, non dovresti davvero cercare modi per restituire un tipo anonimo. Invece, dovresti creare un tipo che può essere restituito poiché questo è il modo corretto per implementare questa funzione.

Pertanto, si consiglia di creare una definizione concreta del tipo da restituire e quindi inserire nella query per restituirla.

+0

... ricordando malinconicamente l'oggetto recordset dal classico ASP ... sembra che questo sia un compromesso tra la complessità del codice e le prestazioni ...per un piccolo programma un grosso problema, ma su un progetto più ampio con centinaia di chiamate db, per un oggetto personalizzato per ogni set di dati recuperati, e avendo a cambiarle se i cambiamenti db, suona come un dolore e l'aumento della complessità del codice .. . – alchemical

+0

Ed è allora che si dovrebbe prendere in considerazione se si sta utilizzando la tecnologia giusta per il lavoro che stai facendo. Non usare una vanga quando quello di cui hai bisogno è un martello. –

+0

così, come potrei semplicemente avere un tipo di oggetto "recordset", cioè che memorizza tutti i tipi restituiti come oggetti avvolti in un oggetto Net standard che posso muoversi facilmente? – alchemical

6

L'utilizzo di var non lo rende un tipo anonimo. L'uso di var significa semplicemente che questa variabile sia del tipo disponibile sul lato destro del compito. È solo una mano corta. Se la cosa sul lato destro è una vera classe, la variabile sarà di quel tipo.

Ad esempio:

var person = new Person { Name = "bob" }; 

La variabile persona è di tipo una persona, anche se ha usato la parola chiave var.

I tipi anonimi vengono creati utilizzando il nuovo {Nome = ...}. In questo caso è una nuova classe anonima.L'unica cosa a cui puoi assegnarlo è una variabile definita usando var (o oggetto) poiché non esiste un nome esistente da usare.

Ad esempio:

var person = new { Name = "bob" }; 

In questo caso, la persona è un tipo anonimo definito in fase di esecuzione.

In generale, come dice @Chalkey, se si vuole passare il risultato a un altro metodo, utilizzare un tipo di nome, non un anonimo.

Se si è obbligati a utilizzare un tipo anonimo, è necessario passarlo indietro come oggetto di tipo Object, quindi utilizzare la riflessione per ottenere le sue proprietà.

+0

Ho provato questo con il mio codice, ma la variabile nuovo nome ("persona" nel tuo esempio), non certo in IntelliSense come un tipo di ritorno utilizzabile per il metodo ... – alchemical

+0

avresti bisogno di inserire il codice per la vostra metodo per me per darti altri consigli. – tvanfosson

+0

Thx, ho appena aggiunto il codice alla domanda. – alchemical

0

Se è necessario passare in rassegna i risultati in un'app di grandi dimensioni, è possibile utilizzare Dizionario. Sì, hai un sovraccarico durante il casting ma almeno stai riducendo gli oggetti buttati via.

2

In genere dipende dal modo in cui il codice chiamante utilizzerà i dati.

Se si sta eseguendo un semplice bind di dati, in realtà non interessa il tipo (ovvero non è necessario accedere in modo esplicito alle proprietà nel codice C#), è possibile restituire i risultati come IEnumberable.

Nella maggior parte dei casi di associazione dati che si sta chiamando per nome le proprietà, tramite corde magiche, in ogni caso, in modo che il tipo esatto non importa comunque.

In caso contrario, è necessario convertire il tipo anonimo in un tipo denominato.