2012-12-28 7 views
5

Ich habe eine Funktion, die ein Objekt zurückgibt, das einen Datensatz in meiner Datenbank plus zusätzliche Spalten darstellt. Anstatt eine separate Klasse für dieses Objekt erstellt ich mich gefragt, ob es eine andere Möglichkeit ist, zum Beispiel:Rückgabedatentyp einer linq Abfrage

public object GetRecord(string key) 
{ 
    var item = select new {column1, column2}; 

    return item; 
} 

public void main() 
{ 
    var item = GetRecord(1); 

    // I want to be able to reference column1 on item. 
    var x = item.column1; 
} 

Antwort

8

Ja, es gibt andere Möglichkeiten (ziemlich viele tatsächlich), aber ich schlage vor, dass Sie keine von ihnen verwenden. Die beste Möglichkeit, diesen Fall zu bearbeiten, besteht darin, einen neuen benutzerdefinierten Typ zu erstellen, der die Daten enthält, die Sie haben. Es wird bei weitem die wartungsfreundlichste Option sein.

Anonyme Typen wurden speziell für den Einsatz im Rahmen einer einzigen Methode entwickelt. Sie kämpfen gegen das Design der Funktionalität, die Sie sonst tun müssen, und so wird es schwierig sein, Sie werden Intellisense wahrscheinlich verlieren, die Leistung wird höchstwahrscheinlich leiden und der arme SAP, der zurückkommen und den Code pflegen muss habe keine Ahnung, was los ist oder wie ich die Abfrage anpassen soll.

Das primäre Problem mit den meisten alternativen Lösungen ist, dass Sie die Überprüfung der Kompilierzeit verlieren. Wenn die Abfrage einen Parameter entfernt, einen Parameter hinzufügt, einen Typ ändert, usw., hat der Code, der ihn verwendet, keine Möglichkeit zu wissen. Wenn Sie Code schreiben, um eine Abfrage zu verwenden, haben Sie keine Möglichkeit zu wissen, was alle Daten sind, was ihre Typen sind, wie die Namen der Variablen lauten usw. Sie müssen sich über Tippfehler in Variablennamen Gedanken machen, die der Compiler kann Fangen Sie nicht, und Sie müssen sich ständig die internen Abläufe der Methode ansehen, die die Abfrage generiert. Sie verlieren die Fähigkeit, es als Black Box oder Abstraktion zu behandeln, was von Bedeutung ist.

Wenn Sie über die Zeit und den Aufwand für die Erstellung dieser benutzerdefinierten Typen besorgt sind, gibt es eine Reihe automatisierter Tools, die solche Klassen basierend auf Datenbanktabellen oder anderen Quellen generieren können.

+1

+1, ich sehe keinen Grund, _not_ keinen benutzerdefinierten Typ zu erstellen. –

6

Wenn es .net 4.0 Verwendung dynamic Schlüsselwort ist.

+0

Ich benutze dynamische, aber ich nehme den Spaltennamen wi an Ich werde nicht im Intellisense erscheinen. wird aber zur Laufzeit funktionieren. – Arcadian

+0

Wenn Sie sich in einem anderen Bereich befinden, in dem Sie Ihren dynamischen Typ erstellt haben, funktioniert Intellisense nicht. –

+0

Für Intellisense müssen Sie einen konkreten Typ verwenden (der in der SELECT-Klausel nicht geändert werden kann). Siehe dazu die Antwort von Felipe. – Tilak

2

nur ergänzend zu den anderen Antworten, könnten Sie auch Generics verwenden, um dies zu tun. so etwas wie dieses:

public T GetRecord<T>(string key) 
    where T : IAnyInterfaceWithProperties, new 
{ 
    var item = select new T { PropertyOfInterface = value, Property2 = value2 }; 

    return item; 
} 
+1

Dies ist voller Syntaxfehler. Setzen Sie die Einschränkung "new" nach der Schnittstelleneinschränkung und entfernen Sie die Umwandlung in "T" und "Auswahl". – Adam

+0

Danke für die Tipps @codesparkle. Ich dachte in diesem Fall, wir müssen wirklich Schlüsselwort "auswählen"? –

3

Auch wenn es .NET 4.0 ist, können Sie ein Tuple<object,object> dann durch item.Item1 Referenz verwenden. Sie können die Eingabe der Objekte anstelle von einfach object verwenden.

public Tuple<Column1Type,Column2Type> GetRecord(string key) 
{ 
    var item = select new Tuple<Column1Type,Column2Type>(column1, column2); 

    return item; 
} 
1

Sie könnten eine POCO-Bibliothek dafür in Betracht ziehen - wird genau das tun, was Sie wollen.

Sie können Ihre eigene Rolle oder ein verwenden, die bereits vorhanden ist:

http://code.google.com/p/dapper-dot-net/

Ihr Code würde dann wie folgt aussehen:

var result = connection.Query("select col1, col2 from table1"); 

var x = result[0].col1; 

Drapper können Sie auch eine starke Art haben zB:

var result = connection.Query<myType>("select col1, col2 from table1"); 

' Now result is a list of myType