实现实体框架查询

时间:2013-06-09 16:07:01

标签: 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;

但是 - 当然 - 这不会产生预期的结果,因为“perf”对象将包含一个InstrumentPerformance集合,其中包含每个1:n加入的InstrumentPerformance实体(无论其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 个答案:

答案 0 :(得分:1)

可以首先检索一个对象,然后通过以下方式创建词典:

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的{​​{1}}个实体。这是因为EF运行称为 relationship fixup 的过程,当从数据库中提取子对象时,它们将子对象绑定到右父对象。

所以现在你可以处理上下文以及之后的任何时间

PortfolioScenarioID == 6013

或使用var perf = query.First(i => i.InstrumentID == 407240).InstrumentPerformance; 代替from i in query来构建词典。

重要提示:应禁用延迟加载,否则EF会在解决后仍尝试加载完整的收藏。

答案 1 :(得分:0)

查看EntityCollection<T> CreateSourceQueryAttach。我想你可以这样做(未经测试):

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集合,而无需了解查询的详细信息。