如何在LinqPad网格结果中展平元组?

时间:2014-11-20 09:49:52

标签: linqpad

通常需要显示数据库表的简单连接的完整结果:

from x in tablex
join y in tabley on x.id equals y.id
select new { x, y }

然而,结果不是您使用等效的SQL语句得到的结果:

SELECT * FROM tablex x JOIN tabley y ON x.id = y.id

SQL为我提供了一个包含两个表中所有列的结果表,而LinqPad将返回一个只有两列的表,只需点击一下即可展开各个对象。

有没有一种简单的方法可以从LinqPad中的类似SQL获得相同的输出?

1 个答案:

答案 0 :(得分:0)

您可以使用Reflection获取所有对象字段/属性,并将它们填充到一个System.Dynamic.ExpandoObject

这是执行此操作的简单扩展方法: LINQPad script Flatten extension method

void Main()
{
    new {x=1, 
        y = new { a = "a", b = "b" },
        DateTime.Now
    }
    .Dump("Original")
    .Flatten(1,false)
    .Dump("Flattened")
    ;
}

public static class Flattener {
    public static object Flatten(this object o, int level = 1, bool includeParent = false){
        if( level == 0 ) return o;
        var members = o.GetMemberValues(level, includeParent);
        var d = new System.Dynamic.ExpandoObject() as IDictionary<string,object>;
        foreach(var p in members) d.Add( p.Key, p.Value );
        return d;
    }

    private static IEnumerable<KeyValuePair<string,object>> GetMemberValues(this object o, int level = 1, bool includeParent = true, string keyPrefix = null){
        if( level < 0 ) yield break;

        var properties = 
            from p in o.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)
            let get = p.GetGetMethod()
            where get != null && get.GetParameters().Length == 0
            select new { p.Name, Value = get.Invoke(o, null) } 
        ;
        var fields = 
            from p in o.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance)
            select new { p.Name, Value = p.GetValue(o) } 
        ;

        foreach(var m in new []{ properties, fields }.SelectMany(x=>x)) {
            string mkey = keyPrefix == null ? m.Name : keyPrefix + "." + m.Name;
            bool empty = true;
            foreach(var m2 in m.Value.GetMemberValues( level-1, includeParent, mkey)){
                yield return new KeyValuePair<string,object>( m2.Key, m2.Value);
                empty = false;
            }
            if(includeParent || empty || level == 0) yield return new KeyValuePair<string,object>( mkey, m.Value);
        }       
    }
}