views:

389

answers:

3

I'm using DbLinq which should be the equivalent of Linq2SQL for this question. I'm need to generate a Linq2SQL query where I specify the columns I want returned at runtime. I can achieve that using the Dynamic Linq extension methods but I can't work out how to extract the result.

string someProperty = "phonenumber";
string id = "1234";

Table<MyClass> table = context.GetTable<MyClass>();
var queryResult = (from item in table where item.Id == id select item).Select("new (" + someProperty + ")");

The Linq expression generates the proper SQL of:

select phonenumber from mytable where id = '1234'

And in the debugger I can see the phonenumber value is sitting there in the Results View. The problem is I can't work out how to get the phonenumber value from the queryResult object? The type of queryResult is:

QueryProvider<DynamicClass1>

Edit: I discovered a way to do it but it seems very crude.

IEnumerator result = (from item in table where item.Id == id select item).Select("new (" + someProperty + ")").GetEnumerator();
result.MoveNext();
var resultObj = result.Current;
PropertyInfo resultProperty = resultObj.GetType().GetProperty(someProperty);
Console.WriteLine(resultProperty.GetValue(resultObj, null));

Perhaps someone knows a cleaner way?

A: 

Linq uses deferred execution method to get data. Deferred execution means that the evaluation of an expression is delayed until its realized value is actually required.

In your case queryResult is a IEnumerable object, which means no data has actually been evaluated yet. You can evaluate queryResult object by calling result.ToList() or result.ToDictionary(), or any other methods that will return an object with non-IEnumerable data types.

Hope this is helpful.

wschenkai
The problem there is the Dynamic Linq Select extension method returns an IQueryable object and not an IQueryable<T> object. The result of that is none of the handy ToList etc. methods are available. Although I guess ultimately those methods must just be using the IEnumberator nder the hood anyway.
sipwiz
A: 

The dynamic aspects of your solution force you to use reflection. You could use the "ElementType" property of the IQueryable rather than getting the first item and reading it's type. Then, a loop like this may be better:

var result = (from item in table where item.Id == id select item).Select("new (" + someProperty + ")");
PropertyInfo resultProperty = result.ElementType.GetProperty(someProperty);
foreach (var resultObj in result)
{
    var value = resultProperty.GetValue(resultObj, null);
}

Short of creating functions to do some of this work for you, there isn't much left to improve. The compiler just doesn't know what's in the object, since it's dynamic. So all the niceness of non-reflective code is unavailable.

John Fisher
A: 

The solution was:

string someProperty = "phonenumber";
PropertyInfo property = typeof(T).GetProperty(propertyName);
string id = "1234";
Table<MyClass> table = context.GetTable<MyClass>();
Expression<Func<T, Object>> mySelect = DynamicExpression.ParseLambda<T, Object>(property.Name);
var query = (from asset in table where asset.Id == id select asset).Select(mySelect);
return query.FirstOrDefault();
sipwiz