Entity framework 实体化框架查询
我使用entity framework 5进行如下查询: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
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
。无论如何,你是对的,如果你需要一次加载数千个,这是没有用的。格特的解决方案可能正适合你。我个人使用的是递归关系(这在单个查询中是不可能实现的),我是按需加载的,而不是预先加载的