从LINQ查询中获取值

时间:2010-11-17 17:46:47

标签: c# .net linq

如何在下面的DoIt函数中获取查询中的一个新属性的值?

public object GetData()
{
       var table = GetDataTable();
       var view = table.DefaultView;
       //..... more code
       var query = from row in view.ToTable().AsEnumerable()
                    group row by row.Field<string>("ShortName") into grouping
                    select new
                        {
                            ShortName = grouping.Key,
                            SCount = grouping.Sum( count => count.Field<int>("ProfCount")),
                            DisplayText = string.Empty
                        };
        return query;
}

// this code doesn't work
public void DoIt()
{
  var result = GetData();
  string shortName = result.ShortName;
}

谢谢!

5 个答案:

答案 0 :(得分:4)

匿名类型不会被称为匿名类型。所以:

定义一个带有名称的类型(另外6行代码):

public class Foo
{
    public string ShortName { get; set; }
    public int SCount { get; set; }
    public string DisplayText { get; set; }
}

现在将GetData签名修改为(0行代码):

public IEnumerable<Foo> GetData()

你的LINQ查询(3个额外的字符,或者如果你选择更有意义的名字,还有几个字符):

var query = 
    from row in view.ToTable().AsEnumerable()
    group row by row.Field<string>("ShortName") into grouping
    select new Foo
    {
        ShortName = grouping.Key,
        SCount = grouping.Sum( count => count.Field<int>("ProfCount")),
        DisplayText = string.Empty
    };

答案 1 :(得分:2)

您将返回一个匿名类型(通过select new {}),该类型仅在本地范围内有效。您需要创建一个具体类型并从函数而不是对象返回它。

public SomeClass GetData()
{
       var table = GetDataTable();
       var view = table.DefaultView;
       //..... more code
       var query = from row in view.ToTable().AsEnumerable()
                    group row by row.Field<string>("ShortName") into grouping
                    select new SomeClass
                        {
                            ShortName = grouping.Key,
                            SCount = grouping.Sum( count => count.Field<int>("ProfCount")),
                            DisplayText = string.Empty
                        };
        return query;
}

// this code doesn't work
public void DoIt()
{
  var result = GetData();
  string shortName = result.ShortName;
}

public class SomeClass
{
    public string ShortName { get; set; }
    public int SCount { get; set; }
    public string DisplayText { get; set; }
}

答案 2 :(得分:1)

好吧,DoIt不知道result有一个名为ShortName的属性,因为它的类型为object。您可以创建一个包含结果,使用反射或使用dynamic的具体类。请注意,无论哪种方式,GetData实际上都返回IEnumerable<T>,其中T目前是匿名类型。

使用具体类:

public class Foo {
    public string ShortName { get; set; }
    public int SCount { get; set; }
    public string DisplayText { get; set; }
}

public IEnumerable<Foo> GetData() {
   var table = GetDataTable();
   var view = table.DefaultView;
   //..... more code
   var query = from row in view.ToTable().AsEnumerable()
                group row by row.Field<string>("ShortName") into grouping
                select new Foo
                    {
                        ShortName = grouping.Key,
                        SCount = grouping.Sum( count => count.Field<int>("ProfCount")),
                        DisplayText = string.Empty
                    };
    return query;
}

public void DoIt() {
    var result = GetData();
    foreach(var item in result) {
        Console.WriteLine(item.ShortName);
    }
}

使用反射:

public IEnumerable GetData() {
    var table = GetDataTable();
    var view = table.DefaultView;
    //..... more code
    var query = from row in view.ToTable().AsEnumerable()
                group row by row.Field<string>("ShortName") into grouping
                select new Foo
                    {
                        ShortName = grouping.Key,
                        SCount = grouping.Sum( count => count.Field<int>("ProfCount")),
                        DisplayText = string.Empty
                    };
    return query;
}

public void DoIt() {
    var result = GetData();
    PropertyInfo property = result.First().GetType().GetProperty("ShortName");
    foreach(var item in result) {
        string shortName = property.GetValue(item, null);
        Console.WriteLine(shortName);
    }
}

答案 3 :(得分:0)

你不能不使用反射。由于它是匿名类型,因此您无法在DoIt()方法中转换它,因为在编译时不知道类型名称。

答案 4 :(得分:0)

这给了我所需要的东西:

public object GetData()
{
       var table = GetDataTable();
       var view = table.DefaultView;
       //..... more code
            var query = from row in view.ToTable().AsEnumerable()
                    group row by row.Field<string>("ShortName") into grouping
                    select new Object[]
                        {
                            grouping.Key,
                            grouping.Sum( count => count.Field<int>("ProfCount")),
                            string.Empty 
                        };
            return query;
}


public void DoIt()
{
  // Note: Pretend that GetData returned only one result
  object[] result = GetData() as object[];
  var shortName = result[0];
}