Материализовать запрос структуры объекта

Я использую Entity Framework 5 для запроса, как это:

var query = 
    from i in context.Instrument
    from p in i.InstrumentPerformance  // 1 : n
    where p.PortfolioScenarioID == 6013
    select i;

Я хочу сохранить запрашиваемое представление этого (отфильтрованного) запроса в памяти. В идеале я мог бы отключить контекст и по-прежнему запрашивать определенную коллекцию InstrumentPerformance, например, так:

var perf = query.First(i => i.InstrumentID == 407240).InstrumentPerformance;

Но это, конечно, не дает желаемого результата, так какперфорация» Объект будет содержать коллекцию InstrumentPerformance, которая содержит каждую присоединенную сущность InstrumentPerformance 1: n (независимо от того, является ли ее идентификатор PortfolioScenarioID 6013 или нет), и он будет извлекать эти сущности с помощью отложенной загрузки с context.ContextOptions.LazyLoadingEnabled = false (или контекстом, выполняемым вне области действия. ) запрос не даст ничего.

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

Поэтому мой вопрос: каков рекомендуемый метод для получения такого представления в памяти?

РЕДАКТИРОВАТЬ: я в настоящее время использую два словаря для кэширования данных, например:

var instruments = (
    from i in context.Instrument
    from p in i.InstrumentPerformance
    where p.PortfolioScenarioID == 6013
    select i)
    .ToDictionary (i => p.InstrumentID, i => i);

var performances = (
    from i in context.Instrument
    from p in i.InstrumentPerformance
    where p.PortfolioScenarioID == 6013
    select p)
    .ToDictionary (p => p.InstrumentID, p => p);

Тем не менее, для этого требуются два обращения к базе данных, причем одна из них кажется достаточной, и, что более важно, семантика для запроса данных о производительности (которая теперь является производительностью [InstrumentID]) не согласуется с способом запроса EF (который должен быть instrument.InstrumentPerformance.First ( ) и тому подобное).

Ответы на вопрос(2)

Решение Вопроса

Сначала можно получить объекты за один дубль, а затем создать словари:

var query = 
    (from i in context.Instrument
    select new { 
                 i,
                 ps = i.InstrumentPerformance
                          .Where(p.PortfolioScenarioID == 6013)
               }).AsEnumerable()
               .Select(x => x.i);

Это материализует и выбираетInstrument лица и здесьтрюк, ихчастично загружен InstrumentPerformance коллекции. То есть инструменты содержат толькоInstrumentPerformance лица, которые отвечают условиюPortfolioScenarioID == 6013, Это потому, что EF запускает процесс, известный какисправление отношений который связывает дочерние объекты с правым родительским объектом, когда они выбираются из базы данных.

Так что теперь вы можете распоряжаться контекстом и в любое время после этого делать

var perf = query.First(i => i.InstrumentID == 407240).InstrumentPerformance;

или создайте свои словари, используяfrom i in query вместо .from i in context.Instrument

ВАЖНЫЙ:отложенная загрузка должна быть отключенаиначе EF все равно попытается загрузить полные коллекции, когда они будут адресованы.

 TvdH10 июн. 2013 г., 14:58
Это происходит, когда запрос выполняется на сервере. Я могу выполнить запрос в Mngmt Studio и также получу сообщение об ошибке нехватки памяти, потому что InstrumentPerformance соединен с собой по InstrumentID - возвращая слишком много записей. Может быть.Where(bool) в вашем примере это так, и я не могу его использовать, потому что мне не хватает расширения?
 TvdH10 июн. 2013 г., 17:16
спасибо, отлично работает сейчас (еще нужно.Where(p => p.PortfolioScenarioID == 6013 запустить его в моем окружении)
 TvdH10 июн. 2013 г., 12:27
Я старался.Where(pf => pf.PortfolioScenarioID == 6013) а также.Where(pf => p.PortfolioScenarioID == 6013) но в обоих случаях sql выдает исключения из памяти. Может быть, требуется лишь небольшое изменение, чтобы получить этот многообещающий подход к работе? Я не могу понять.
 TvdH10 июн. 2013 г., 15:35
Да, Instrument / InstrumentPerformance объединяются 1: n на InstrumentID (и эта ассоциация кажется нормальной в модели, т.е.Instrument.First().InstrumentPerformance возвращает только данные InstrumentPerformance для первого инструмента). Надеюсь, это проиллюстрирует:ссылка на сайт
 Gert Arnold10 июн. 2013 г., 15:44
Ааа ... небольшой глюк в моем запросе. Это'Еще проще :)
 Gert Arnold10 июн. 2013 г., 15:06
Isn»Неужели это недостаток в ассоциациях? Я думаюInstrumentPerformance должен быть ФК (InstrumentInstrumentID). Я нене вижу, как вы можете присоединиться к егоInstrumentID с собой. Может быть, показать модель данных, чтобы уточнить.
 Gert Arnold10 июн. 2013 г., 12:34
Трассировка стека по-прежнему доступна и можете ли вы указать, куда выдается исключение памяти? Я могу'не понимаю, почему это должно произойти, яу нас есть похожие запросы, работающие в порядке.

смотреть наEntityCollection CreateSourceQuery а такжеПрикреплять, Я думаю, что вы могли бы сделать это (не проверено):

var instrumentQuery = 
    from i in context.Instrument
    from p in i.InstrumentPerformance  // 1 : n
    where p.PortfolioScenarioID == 6013
    select i;
var instruments = instrumentQuery.ToList();
foreach (var instrument in instruments) {
    var performanceQuery =
        instrument.InstrumentPerformance.CreateSourceQuery()
            .Where(p => p.PortfolioScenarioID == 6013);
    instrument.InstrumentPerformance.Attach(performanceQuery);
}

Это выполняет все сразу (без отложенной загрузки) и имеет небольшое дублирование кода, но это приведет к спискуInstrument где каждыйi.InstrumentPerformance возвращает отфильтрованную коллекцию, то есть любой последующий код, который работает с ней, может обрабатывать ее как любую другую коллекцию EF без необходимости знать детали запроса.

 TvdH10 июн. 2013 г., 00:19
Я попробовал этот интересный подход. "для каждого" является проблемой, потому что он производит обходы БД в десятки тысяч и по какой-то причине фильтр p.PortfolioScenarioID == 6013 не работает. Похоже, что данные были материализованы, и я могу отключить контекст и по-прежнему получать доступ к инструменту. First (). InstrumentPerformance, так что это хорошо, но пропущенный оператор where и цикл foreach в настоящее время делают это непрактичным для моего приложения.
 nmclean10 июн. 2013 г., 03:56
@ TVDH я нене знаю, почему фильтр нене работает ... вам может понадобиться позвонитьExecute и передать результат этогоAttach вместо. Во всяком случае, тыверно, это не хорошо, если вам нужно загружать тысячи одновременно. Герта»Решение, вероятно, является правильным для вас. То, что я использовал это для себя, это рекурсивные отношения (которые неЭто действительно возможно сделать с помощью одного запроса), и я загружал их по требованию, а не авансом.

Ваш ответ на вопрос