2013-07-24 5 views
0

Я работаю над приложением MVC. Многие из них - поисковая система, позволяющая пользователю выбирать параметры для получения желаемых данных.MVC Эффективные динамические вызовы базы данных EF

Я ищу эффективный способ динамических вызовов в базу данных, чтобы я мог получать только нужные данные вместо того, чтобы брать кучу данных и сортировать их.

До сих пор я использовал Dynamic Linq, но у меня были огромные проблемы с этим, и мне было интересно, было ли что-то лучше и менее хлопотно. Единственным фактором является то, что я знаю поля таблицы, которую я ищу, и мне нужно иметь возможность использовать таких операторов, как >, < или =.

EDIT

Вот пример таблицы на основе моего приложения:

TABLE CARD 
(
    CARD_IDE INT NOT NULL IDENTITY, 
    CARD_NAME VARCHAR(50) NOT NULL, 
    CARD_NUMBER NUMERIC(4) NOT NULL, 
    CARD_COLOR VARCHAR(10), 
    CARD_MANA_COST VARCHAR(30), 
    CARD_MANA_CONVT VARCHAR(3), 
    CARD_TYPE VARCHAR(50), 
    CARD_POWER VARCHAR(2), 
    CARD_TOUGH VARCHAR(2), 
    CARD_RARTY VARCHAR(1) NOT NULL, 
    CARD_TEXT_ABILT VARCHAR(800), 
    CARD_TEXT_FLAVR VARCHAR(800), 
    CARD_ARTST_NAME VARCHAR(100), 
    CARD_SET_IDE INT NOT NULL, 
    CARD_FLAG_FACE INT NOT NULL DEFAULT 0, 
    CARD_CHILD_IDE INT, 
    CARD_MASTER_IDE INT, 
    CARD_UNIT_COST NUMERIC(5,2) NOT NULL DEFAULT 0 
) 

И несколько примеров:

  1. пользователь ищет любой предмет, какой тип является "Creature" (String), число является 3 и набор карт IDE: 6;
  2. Фотографии, содержащие слово Rat;
  3. Все карты colorBlue и White которого стоимость единицы является higher than 3.00
  4. Любые карты, которые power меньше, чем 3 но выше, чем 1.

EDIT 2

После долгих исследований (и благодаря Прэтт ниже), мне удалось посмотреть немного и погружение во что-то.

на основе this:

Сначала я создаю свой контекст объекта, как это:

var objectContext = ((IObjectContextAdapter) mDb).ObjectContext; 

Тогда я создать ObjectSet:

ObjectSet<CARD> priceList = objectContext.CreateObjectSet<CARD>(); 

Затем я проверяю, если какие-либо значения, как были выбраны от пользователя:

if (keyValuePair.Key == CARDNAME) 
{ 
    queryToLoad = TextBuilder.BuildQueryStringForTextboxValue(keyValuePair.Value); 

    //valuesToUse.Add("CARD_NAME.Contains(\"" + queryToLoad + "\")"); 

    priceList = priceList.Where(_item => _item.CARD_NAME.Contains(queryToLoad)) as ObjectSet<PRICE_LIST>; 
} 

Где queryToLoad - это, по сути, значение, которое нужно искать. Пример: если мой пользователь ищет Ангел, queryToLoad будет «Ангел». Я пытаюсь получить результат без необходимости переписывать весь код.

А потом собрать результат в списке, как это:

listToReturn.AddRange(priceList.ToList()); 

ОДНАКО: У меня есть проблема с использованием этого подхода. Поскольку priceList = priceList.Where(_item => _item.CARD_NAME.Contains(queryToLoad)) as ObjectSet<PRICE_LIST>; нравится, это значение всегда null, и я не знаю почему.

+0

Можно привести примеры, которые более конкретны, если вы предоставите некоторый код. – mostruash

+0

Я поставлю стол и несколько примеров, чтобы он стал конкретным. – hsim

+0

Добавлен код. У вас есть вопросы? – hsim

ответ

1

Невозможно оптимизировать то, что по своей природе является динамичным по своей природе. Единственное, что вы можете сделать в своем приложении, - это подавать любые фильтры, которые конечный пользователь выбирает в предложении Where, и позволить Entity Framework извлекать результат из вашей базы данных самым эффективным способом, который он считает нужным.

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

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

UPDATE

Вот что я имею в виду, создавая запрос. Я рассмотрю ваш первый сценарий использования. У вас есть три фильтра: тип, число и IDE. Пользователь может указать один или два, все три или ни одного. (Мы предполагаем, что cardType является строкой и cardNumber и cardIde являются обнуляемыми Интсами.

var cards = db.Cards; 

if (!string.IsNullOrEmpty(cardType)) 
{ 
    cards = cards.Where(m => m.Type == cardType); 
} 

if (cardNumber.HasValue) 
{ 
    cards = cards.Where(m => m.Number == cardNumber); 
} 

if (cardIde.HasValue) 
{ 
    cards = cards.Where(m => m.IDE == cardIde); 
} 

return View(cards); 

Entity Framework будет на самом деле не выдавать запрос, пока вы не сделаешь то, что требует данных из запроса (итерации по списку, подсчет элементов и т. д.). До этого момента все, что вы делаете с DbSet, просто привязано к запросу, которое EF в конечном итоге отправит. Поэтому вы можете построить свой запрос, условно обрабатывая каждый потенциальный фильтр по одному, прежде чем, наконец, используя конечный результат.

ОБНОВЛЕНИЕ # 2

Извините, я, видимо, еще не потреблял достаточно кофе, когда обновлял свое последнее обновление. Там, очевидно, проблема с типом. Если вы храните db.Cards в cards, это будет тип DbSet<Card>, в то время как результатом любого вызова Where будет тип IQueryable<Card>, который, очевидно, не может быть сохранен в той же переменной.

Так что вам просто нужно сначала привести переменную к чему-то, что работает для обоих: IEnumerable<Card>:

IEnumerable<Card> cards = db.Cards; 

Тогда вы не должны получить какие-либо ошибки типа.

+0

Спасибо за ваше объяснение, это очень интересно. Вы упомянули, что я могу построить предложение 'Where', основанное на выборе пользователя. Простой вопрос: как я могу это сделать, если есть много вариантов, сделанных, как в моих примерах выше? – hsim

+0

Дело в том, что я понимаю, о чем вы говорите, но на основе я просто не знаю, как это сделать.: S – hsim

+0

Я был немного упрощен; реальность такова, что вы должны * построить * запрос, который включает в себя несколько вызовов в «Где», но пока вы не получаете доступ к результату, EF отправляет только один запрос в конце. Я обновлю свой ответ выше, чтобы привести пример. –

Смежные вопросы