Как использовать словарь или Hashtable для производительности запросов LINQ под службой OData - PullRequest
0 голосов
/ 17 ноября 2011

Я очень новичок в OData (только начал его вчера), поэтому извините, если этот вопрос слишком тупой: -)

Я создал тестовый проект в качестве проверки концепции для переноса наших текущих веб-сервисов на OData. В этом тестовом проекте я использую Reflection Providers для предоставления классов POCO через OData. Эти классы POCO поступают из кеша в памяти. Ниже приведен код:

public class DataSource
{
    public IQueryable<Category> CategoryList
    {
        get
        {
            List<Category> categoryList = GetCategoryListFromCache();
            return categoryList.AsQueryable();
        }
    }
    // below method is only required to allow navigation
    // from Category to Product via OData urls
    // eg: OData.svc/CategoryList(1)/ProductList(2) and so on
    public IQueryable<Category> ProductList
    {
        get
        {
            return null;
        }
    }
}

[DataServiceKeyAttribute("CategoryId")]
public class Category
{
    public int CategoryId { get; set; }
    public string CategoryName { get; set; }
    public List<Product> ProductList { get; set; }
}

[DataServiceKeyAttribute("ProductId")]
public class Product
{
    public int ProductId { get; set; }
    public string ProductName { get; set; }
}

Насколько мне известно, OData собирается использовать LINQ за кулисами для запроса этих объектов в памяти, а именно: в этом случае перечислить, если кто-то перейдет к OData.svc / CategoryList (1) / ProductList (2) и т. д.

Однако проблема в следующем: в сценарии реального мира я просматриваю более 18 миллионов записей в кэше, представляющих более 24 различных объектов.

Современные производственные веб-сервисы очень хорошо используют .NET Dictionary и коллекции Hashtable, чтобы обеспечить очень быстрый поиск и избежать большого количества циклов. Таким образом, чтобы перейти к продукту с ProductID 2 в категории, имеющей CategoryID 1, текущие веб-сервисы просто выполняют 2 поиска, то есть: первый - для поиска категории, а второй - для поиска продукта внутри категории. Что-то вроде btree.

Я хотел знать, как я мог следовать аналогичной архитектуре с OData, где я мог бы указать OData и LINQ использовать Dictionary или Hashtables для поиска записей, а не зацикливаться на общем списке?

Возможно ли использование поставщиков отражений или у меня нет другого выбора, кроме как написать свой собственный поставщик для OData?

Заранее спасибо.

1 Ответ

1 голос
/ 17 ноября 2011

Вам потребуется обработать деревья выражений, поэтому вам потребуется хотя бы частичная реализация IQueryable поверх базовых LINQ to Objects. Для этого вам не нужен полноценный пользовательский провайдер, просто верните IQueryable из свойств контекстного класса. В этом IQueryable вам придется распознавать фильтры по ключевым свойствам (.Where (p => p.ProductID = 2)) и переводить их в словарь / поиск по хеш-таблице. Затем вы можете использовать LINQ для объектов для обработки остальной части запроса. Но если клиент выдаст запрос с фильтром, который не касается свойства ключа, он в конечном итоге выполнит полное сканирование. Хотя ваш пользовательский IQueryable может обнаружить это и завершить такой запрос, если вы выберете это.

...