Итак, вот моя дилемма. Я пытаюсь использовать Dynamic LINQ для анализа фильтра поиска для получения набора записей из таблицы Azure. В настоящее время я могу получить все записи с помощью объекта GenericEntity, определенного ниже:
public class GenericEntity
{
public string PartitionKey { get; set; }
public string RowKey { get; set; }
Dictionary<string, object> properties = new Dictionary<string, object>();
/* "Property" property and indexer property omitted here */
}
Я могу полностью заполнить его, используя событие ReadingEntity объекта TableServiceContext (называемого OnReadingGenericEvent). Следующий код - это то, что фактически извлекает все записи и , надеюсь, фильтр (как только он заработает).
public IEnumerable<T> GetTableRecords(string tableName, int numRecords, string filter)
{
ServiceContext.IgnoreMissingProperties = true;
ServiceContext.ReadingEntity -= LogType.GenericEntity.OnReadingGenericEntity;
ServiceContext.ReadingEntity += LogType.GenericEntity.OnReadingGenericEntity;
var result = ServiceContext.CreateQuery<GenericEntity>(tableName).Select(c => c);
if (!string.IsNullOrEmpty(filter))
{
result = result.Where(filter);
}
var query = result.Take(numRecords).AsTableServiceQuery<GenericEntity>();
IEnumerable<GenericEntity> res = query.Execute().ToList();
return res;
}
У меня есть производные типы TableServiceEntity для всех таблиц, которые я определил, поэтому я могу получить все свойства / типы с использованием Reflection. Проблема с использованием класса GenericEntity в динамическом запросе LINQ для фильтрации заключается в том, что объект GenericEntity НЕ имеет каких-либо свойств, которые я пытаюсь фильтровать, поскольку они на самом деле просто словарные записи (ошибки динамического запроса отсутствуют). Я могу разобрать фильтр для всех имен свойств этого конкретного типа и обернуть
"Property[" + propName + "]"
каждое свойство (найденное с помощью функции распознавания типов и отражения). Однако это кажется немного ... излишним. Я пытаюсь найти более элегантное решение, но поскольку мне действительно нужно указать тип в ServiceContext.CreateQuery <>, это несколько затрудняет.
Итак, я предполагаю, что мой главный вопрос таков: Как я могу использовать динамические классы или универсальные типы с этой конструкцией, чтобы иметь возможность использовать динамические запросы для фильтрации? Таким образом, я могу просто взять фильтр из текстового поля (например, «item_ID> 1023000») и просто динамически сгенерировать типы TableServiceEntity.
Я могу использовать другие способы решения этой проблемы, но с тех пор, как начал используя Dynamic LINQ, можно также попробовать и динамические классы.
Edit: Итак, у меня есть динамический класс, генерируемый первоначальным выбором с использованием некоторого отражения, но я сталкиваюсь с препятствием при сопоставлении типов GenericEntity.Properties в различные связанные классы записей таблицы (производные классы TableServiceEntity) и их типы свойств. Основная проблема по-прежнему заключается в том, что я должен изначально использовать определенный тип данных даже для создания запроса, поэтому я m с использованием типа GenericEntity, который содержит только пары KV. Это в конечном итоге мешает мне фильтровать, так как я не могу выполнять операторы сравнения (>, <, = и т. Д.) С типами объектов.
Вот код, который у меня теперь есть для отображения в динамический класс:
var properties = newType./* omitted */.GetProperties(
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.Public);
string newSelect = "new(" + properties.Aggregate("", (seed, reflected) => seed += string.Format(", Properties[\"{0}\"] as {0}", reflected.Name)).Substring(2) + ")";
var result = ServiceContext.CreateQuery<GenericEntity>(tableName).Select(newSelect);
Может быть, мне просто изменить метод properties.Aggregate, добавив к разделу «Свойства [...]» префикс отраженного.PropertyType? Таким образом, новая строка выбора будет выглядеть так:
string newSelect = "new(" + properties.Aggregate("", (seed, reflected) => seed += string.Format(", ({1})Properties[\"{0}\"] as {0}", reflected.Name, reflected.PropertyType)).Substring(2) + ")";
Edit 2: Итак, теперь я наткнулся на препятствие. Я могу сгенерировать анонимные типы для всех таблиц, чтобы получить все нужные мне значения, но LINQ не справляется с моими действиями, независимо от того, что я делаю для фильтра. Я указал причину выше (нет операторов сравнения для объектов), но проблема я Сейчас мы пытаемся указать параметр типа для метода расширения Dynamic LINQ, чтобы он принял схему нового типа объекта. И тут не особо везет ... Буду держать вас в курсе.