简体   繁体   中英

c# LINQ Dictionary of anonymous type values

I am trying to prepare a dictionary which contains COLUMN_NAME as Key and {IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH} as value.

This is what I have done so far.

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 function which not listed here, works fine and returns me a valid System.Data.DataTable .

Compiler throws...

error CS0029: Cannot implicitly convert type 'System.Collections.Generic.Dictionary>' to 'System.Collections.Generic.Dictionary'

Question is, How do I generate an anonymous object with these properties - IS_NULLABLE , DATA_TYPE , CHARACTER_MAXIMUM_LENGTH ?

If you do not return dictionary outside method you do not need to declare it.

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

you will get Dictionary<string, anonymous type> .

Than you can use your Type:

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

In my opinion it would be much better to create a class DbColumn instead. Then your dictionary is a Dictionary<string, DbColumn> and you can use it also as field or pass it to other methods and you don't have to cast everything everytime as with Object . You can also extend that class with other properties or methods.

However, if you only need this dictionary in that method it would still be better to not store it in a Dictionary<string, Object> to avoid casting.

Therefore you could use var :

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
}

Of course this works only if you just need to use it in the if which seems to be the case.

You must explicitly cast your anonymous object to object type like this:

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

because otherwise compiler creates a dictionary of a different type.

Simply cast your new anonymous object to object , you cannot convert a generic class from a type to another natively.

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

Indeed, your ToDictionary call doesn't return a Dictionary<string, object> , but a Dictionary<string, anonymous type> . Even though anonymous type derives from object , the cast cannot be made with generic types (thus, with Dictionaries).

You won't be able to access your anonymous type's properties with object though, so you should probably use dynamic instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM