O.O
O.O

Reputation: 11287

Get values from LINQ query

How do I get the value of one of the new properties out of query in the DoIt function below?

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

Thanks!

Upvotes: 0

Views: 7990

Answers (5)

O.O
O.O

Reputation: 11287

This gives me what I need:

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

Upvotes: 0

jason
jason

Reputation: 241583

Well, DoIt has no idea that result has a property named ShortName because its typed as an object. You could create a concrete class that holds the results, use reflection, or use dynamic. Note that either way, GetData is really returning an IEnumerable<T> where T is currently an anonymous type.

Using a concrete class:

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

Using reflection:

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

Upvotes: 1

Darin Dimitrov
Darin Dimitrov

Reputation: 1038710

Anonymous types are not called anonymous types for nothing. So:

Define a type with a name (6 additional lines of code):

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

Now modify your GetData signature to (0 additional lines of code):

public IEnumerable<Foo> GetData()

And your LINQ query to (3 additional characters, or a couple more if you choose more meaningful name):

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

Upvotes: 4

James Kovacs
James Kovacs

Reputation: 11651

You're returning an anonymous type (via select new {}), which is only valid in the local scope. You need to create a concrete type and return that from your function rather than object.

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

Upvotes: 2

cdhowie
cdhowie

Reputation: 168978

You can't without using reflection. Since it is an anonymous type, you cannot cast to it in the DoIt() method either, since the type name is not known at compile time.

Upvotes: 0

Related Questions