2017-06-28 3 views
0

Ich versuche ein Wörterbuch vorzubereiten, das COLUMN_NAME als Schlüssel und {IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH} als Wert enthält.C# LINQ Dictionary von anonymen Werten

Das habe ich bisher gemacht.

Dictionary<string, object> dict = new Dictionary<string, object>(); 

var dt = GetDataTable($"SELECT COLUMN_NAME, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='{tableName}'"); 
if (dt != null) 
{ 
    dict = dt.AsEnumerable().ToDictionary(row => row.Field<string>(0), row => new { IS_NULLABLE = row.Field<bool>(1), DATA_TYPE = row.Field<string>(2), CHARACTER_MAXIMUM_LENGTH = row.Field<int>(3) }); 
} 

GetDataTable Funktion, die hier nicht aufgeführt sind, funktioniert gut und gibt mir eine gültige System.Data.DataTable.

Compiler wirft ...

Fehler CS0029: Kann nicht implizit konvertiert Typ 'System.Collections.Generic.Dictionary>' auf 'System.Collections.Generic.Dictionary'

Frage ist , Wie erzeuge ich ein anonymes Objekt mit diesen Eigenschaften - IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH?

+2

Warum erstellen Sie nicht stattdessen eine Klasse 'DbColumn'? Dann ist Ihr Wörterbuch ein 'Dictionary ' –

+0

Ja, das ist einfach zu beheben. Ich kenne. Aber ich möchte dies mit anonymen Typen erreichen. – user1

+0

Warum? Das ist nicht nur eine Lösung, es ist ein viel besserer Ansatz, da Sie dieses Wörterbuch als Feld in einer Klasse verwenden oder als Argument übergeben können. Sie können es später auch erweitern oder Methoden bereitstellen. Sie haben auch kompilierte Zeit Sicherheit und können auf die Eigenschaften zugreifen, ohne sie im Gegensatz zu "Objekt" zu werfen. –

Antwort

3

Wenn Sie das Wörterbuch nicht außerhalb der Methode zurückgeben, müssen Sie es nicht deklarieren.

var dt = GetDataTable(@"SELECT COLUMN_NAME, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='{tableName}'"); 
    var dict = dt?.AsEnumerable()?.ToDictionary(row => row.Field<string>(0), row => new { IS_NULLABLE = row.Field<bool>(1), DATA_TYPE = row.Field<string>(2), CHARACTER_MAXIMUM_LENGTH = row.Field<int>(3) }); 

erhalten Sie Dictionary<string, anonymous type>.

als Sie Ihre Art verwenden können:

if(dict["key"].IS_NULLABLE) MessageBox.Show("yeah...."); 
+0

Wörterbuch-Deklaration war das Hauptproblem in meinem Code. Markieren Sie dies als Antwort, da dies die erste Antwort ist, die das Hauptproblem identifiziert. – user1

1

Sie müssen explizit Ihr anonymes Objekt object Art wie diese Stimmen:

dict = dt.AsEnumerable().ToDictionary(row => row.Field<string>(0), row => (object)new { IS_NULLABLE = row.Field<bool>(1), DATA_TYPE = row.Field<string>(2), CHARACTER_MAXIMUM_LENGTH = row.Field<int>(3) }); 

weil sonst Compiler ein Wörterbuch eines anderen Typs erzeugt.

1

Sie können Ihr neues anonymes Objekt einfach in object umwandeln, Sie können eine generische Klasse nicht von einem Typ in einen anderen konvertieren.

dict = dt.AsEnumerable() 
    .ToDictionary(row => row.Field<string>(0), 
     row => (object)new // Here, we cast the result to object, so the dictionary will actually use the type 'object' and not 'anonymous type' 
      { 
       IS_NULLABLE = row.Field<bool>(1), 
       DATA_TYPE = row.Field<string>(2), 
       CHARACTER_MAXIMUM_LENGTH = row.Field<int>(3) 
      }); 

Tat Ihr ToDictionary Anruf gibt keinen Dictionary<string, object>, sondern eine Dictionary<string, anonymous type>. Auch wenn anonymous type von object abgeleitet wird, kann die Besetzung nicht mit generischen Typen (also mit Wörterbüchern) gemacht werden.

Sie können jedoch nicht mit object auf die Eigenschaften Ihres anonymen Typs zugreifen, also sollten Sie stattdessen dynamic verwenden.

3

Meiner Meinung nach wäre es viel besser, eine Klasse zu erstellen DbColumn statt. Dann ist Ihr Wörterbuch ein Dictionary<string, DbColumn> und Sie können es auch als Feld verwenden oder es an andere Methoden übergeben und Sie müssen nicht jedes Mal wie bei Object alles umwandeln. Sie können diese Klasse auch um andere Eigenschaften oder Methoden erweitern.

Wenn Sie jedoch nur dieses Wörterbuch in dieser Methode benötigen, wäre es immer noch besser, nicht speichern Sie es in einem Dictionary<string, Object> Gießen zu vermeiden.

Daher könnten Sie var verwenden:

var dt = GetDataTable($"SELECT COLUMN_NAME, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='{tableName}'"); 
if (dt != null) 
{ 
    var dict = dt.AsEnumerable().ToDictionary(row => row.Field<string>(0), row => new { IS_NULLABLE = row.Field<bool>(1), DATA_TYPE = row.Field<string>(2), CHARACTER_MAXIMUM_LENGTH = row.Field<int>(3) }); 
    // here you can access all properties of the anonymous type without having to cast 
} 

Natürlich funktioniert dies nur, wenn Sie nur in der if verwenden müssen, was der Fall zu sein scheint.

Verwandte Themen