c#LINQ匿名类型值的字典

时间:2017-06-28 10:56:54

标签: c# linq dictionary

我正在尝试准备一个字典,其中包含COLUMN_NAME作为键,{IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH}作为值。

这是我到目前为止所做的。

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函数正常工作,并返回有效的System.Data.DataTable

编译器抛出......

  

错误CS0029:无法隐式转换类型&#39; System.Collections.Generic.Dictionary&gt;&#39;到&#39; System.Collections.Generic.Dictionary&#39;

问题是,如何使用这些属性生成匿名对象 -  IS_NULLABLEDATA_TYPECHARACTER_MAXIMUM_LENGTH

4 个答案:

答案 0 :(得分:3)

如果你没有在方法之外返回字典,则不需要声明它。

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

您将获得Dictionary<string, anonymous type>

你可以使用你的类型:

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

答案 1 :(得分:3)

在我看来,创建一个类DbColumn会好得多。然后你的字典是Dictionary<string, DbColumn>,你也可以将它作为字段使用或将其传递给其他方法,你不必每次都像Object一样投射所有内容。您还可以使用其他属性或方法扩展该类。

但是,如果你只需要在该方法中使用这个字典,那么将它存储在Dictionary<string, Object>中以避免强制转换仍然会更好。

因此您可以使用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
}

当然,这只有在您需要在if中使用时才有效。

答案 2 :(得分:1)

您必须明确地将您的匿名对象转换为object类型:

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

因为否则编译器会创建不同类型的字典。

答案 3 :(得分:1)

只需将新的匿名对象转换为object,就不能将泛型类从一种类型转换为另一种类型。

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

的确,您的ToDictionary来电不会返回Dictionary<string, object>,而是Dictionary<string, anonymous type>。即使anonymous type派生自object,也无法使用泛型类型(因此,使用词典)进行强制转换。

您将无法使用object访问匿名类型的属性,因此您应该使用dynamic代替。