Entity framework 实体化框架查询

Entity framework 实体化框架查询,entity-framework,Entity Framework,我使用entity framework 5进行如下查询: var query = from i in context.Instrument from p in i.InstrumentPerformance // 1 : n where p.PortfolioScenarioID == 6013 select i; 我想在内存中存储此(过滤)查询的可查询响应。理想情况下,我可以断开上下文连接,并仍然请求特定的性能集合,如下所示: var perf = que

我使用entity framework 5进行如下查询:

var query = 
    from i in context.Instrument
    from p in i.InstrumentPerformance  // 1 : n
    where p.PortfolioScenarioID == 6013
    select i;
我想在内存中存储此(过滤)查询的可查询响应。理想情况下,我可以断开上下文连接,并仍然请求特定的性能集合,如下所示:

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);

但是,这需要对数据库进行两次往返,其中一次似乎足够了,更重要的是,查询性能数据的语义(现在是performances[InstrumentID])与EF查询方式(应该是instrument.InstrumentPerformance.First()等)不一致.

查看
实体集合
和。我认为您可以这样做(未经测试):


这会一次执行所有操作(无延迟加载)并有一点代码重复,但会产生一个
Instrument
列表,其中每个
i.InstrumentPerformance
返回过滤后的集合,这意味着在其上运行的任何后续代码都可以将其视为任何其他EF集合,而无需知道查询的详细信息。

查看
EntityCollection
和。我认为您可以这样做(未经测试):


这会一次执行所有操作(无延迟加载)并有一点代码重复,但会产生一个
Instrument
列表,其中每个
i.InstrumentPerformance
返回过滤后的集合,这意味着在其上运行的任何后续代码都可以将其视为任何其他EF集合,而无需了解查询的详细信息。

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

var query = 
    (from i in context.Instrument
    select new { 
                 i,
                 ps = i.InstrumentPerformance
                          .Where(p.PortfolioScenarioID == 6013)
               }).AsEnumerable()
               .Select(x => x.i);
这将具体化并选择
Instrument
实体,这里是技巧,它们的部分加载
InstrumentPerformance
集合。即,仪器仅包含满足条件的
仪器性能
实体
PortfolioScenarioID==6013
。这是因为EF运行一个称为关系修复(relationship fixup)的过程,该过程在从数据库中提取子对象时将子对象绑定到正确的父对象

因此,现在您可以处理上下文,之后的任何时间都可以进行处理

var perf = query.First(i => i.InstrumentID == 407240).InstrumentPerformance;
或者使用查询中的i
而不是上下文中的i
来构建词典


重要提示:应禁用延迟加载,否则EF在寻址时仍将尝试加载完整集合。

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

var query = 
    (from i in context.Instrument
    select new { 
                 i,
                 ps = i.InstrumentPerformance
                          .Where(p.PortfolioScenarioID == 6013)
               }).AsEnumerable()
               .Select(x => x.i);
这将具体化并选择
Instrument
实体,这里是技巧,它们的部分加载
InstrumentPerformance
集合。即,仪器仅包含满足条件的
仪器性能
实体
PortfolioScenarioID==6013
。这是因为EF运行一个称为关系修复(relationship fixup)的过程,该过程在从数据库中提取子对象时将子对象绑定到正确的父对象

因此,现在您可以处理上下文,之后的任何时间都可以进行处理

var perf = query.First(i => i.InstrumentID == 407240).InstrumentPerformance;
或者使用查询中的i
而不是上下文中的i
来构建词典


重要提示:应禁用延迟加载,否则EF在处理完整集合时仍将尝试加载它们。

我尝试了这个有趣的方法。“foreach”是一个问题,因为它会产生10秒的数千DB往返,并且由于某些原因p.PortfolioScenarioID==6013过滤器无法工作。看起来数据已经具体化了,我可以断开上下文连接,仍然可以访问instrument.First().InstrumentPerformance,所以这很好,但是省略的where子句和foreach循环目前使这对我的应用程序来说不切实际。@TvdH我不知道过滤器为什么不工作。。。您可能需要调用
Execute
并将结果传递给
Attach
。无论如何,你是对的,如果你需要一次加载数千个,这是没有用的。格特的解决方案可能正适合你。我个人使用的是递归关系(这在单个查询中是不可能实现的),我按需加载它们,而不是预先加载。我尝试了这个有趣的方法。“foreach”是一个问题,因为它会产生10秒的数千DB往返,并且由于某些原因p.PortfolioScenarioID==6013过滤器无法工作。看起来数据已经具体化了,我可以断开上下文连接,仍然可以访问instrument.First().InstrumentPerformance,所以这很好,但是省略的where子句和foreach循环目前使这对我的应用程序来说不切实际。@TvdH我不知道过滤器为什么不工作。。。您可能需要调用
Execute
并将结果传递给
Attach
。无论如何,你是对的,如果你需要一次加载数千个,这是没有用的。格特的解决方案可能正适合你。我个人使用的是递归关系(这在单个查询中是不可能实现的),我是按需加载的,而不是预先加载的