Доступ к результату Linq, содержащемуся в динамическом классе

Я использую DbLinq, который должен быть эквивалентом Linq2SQL для этого вопроса. Мне нужно сгенерировать запрос Linq2SQL, где я указываю столбцы, которые я хочу вернуть во время выполнения. Я могу добиться этого, используя методы расширения Dynamic Linq, но я не могу понять, как извлечь результат.

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 + ")");

Выражение Linq генерирует правильный SQL:

select phonenumber from mytable where id = '1234'

И в отладчике я вижу, что значение phonenumber находится в представлении результатов. Проблема в том, что я не могу понять, как получить значение номера телефона из объекта queryResult? Тип запроса:

QueryProvider<DynamicClass1>

Редактировать: я нашел способ сделать это, но это кажется очень грубым.

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

Возможно, кто-то знает более чистый способ?

3 ответа

Решение

Решение было:

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

Linq использует метод отложенного выполнения для получения данных. Отложенное выполнение означает, что оценка выражения откладывается до тех пор, пока его фактическое значение фактически не потребуется.

В вашем случае queryResult является объектом IEnumerable, что означает, что данные еще не были оценены. Вы можете оценить объект queryResult, вызвав result.ToList() или result.ToDictionary(), или любые другие методы, которые будут возвращать объект с типами данных не IEnumerable.

Надеюсь, это полезно.

Динамические аспекты вашего решения заставляют вас использовать рефлексию. Вы можете использовать свойство "ElementType" IQueryable вместо того, чтобы получать первый элемент и читать его тип. Тогда такой цикл может быть лучше:

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

Если не считать создания функций для выполнения некоторых из этих работ для вас, не так много улучшений. Компилятор просто не знает, что находится в объекте, так как он динамический. Так что вся прелесть неотражающего кода недоступна.

Другие вопросы по тегам