我首先使用Entity Framework 6.x数据库和SQL Azure数据库。
我有研究的数据库表和受访者的单独表格。在我的EF设计师中,我有一个研究实体和受访者实体,而研究实体有一个针对受访者的导航属性。每项研究都有数千名受访者,有数百项研究。
我的问题是我正在尝试在Studies表上创建一个包含COUNT个响应者的计算列,并且我正在尝试加载此值。我需要急切加载的原因是因为我正在使用研究列表填充DataGrid(WPF),并且我的网格中的一列是RespondentCount。如果我不急于加载这个值,那么我的数据网格上的滚动就会变得很糟糕,因为当用户滚动网格时,RespondentCounts是延迟加载的。
我当然可以使用此声明加载所有受访者:
ctx.Studies.Include(s => s.Respondents)
然后在“受访者导航”属性上执行.COUNT(),但之后我会在每次研究中加载数千名受访者,这是一个巨大的性能损失和大量浪费的内存,因为我只需要COUNT。
我真正需要的是:
ctx.Studies.Include(s => s.Respondents.Count)
但这不起作用。
我尝试设置一个包含Studies表的Database VIEW,其中包含一个简单的RespondentCount计算字段,但是VIEW只是在Entity Framework中读取,当我将VIEW引入时,我丢失了在Studies表上的所有其他外键关系EF设计师。
如何在不必加载所有受访者的情况下加载此聚合值?
答案 0 :(得分:2)
步骤:
Studies
表中创建一个计算列以使用该新功能。HasDatabaseGeneratedOption
参数设置DatabaseGeneratedOption.Computed
属性。我自己的测试表中的一些潜在代码
create table respondents (id int, study_id int)
create function dbo.CountRespondents (@id int)
returns int
as
begin
return (select count(1) from respondents where study_id = @id)
END
create table studies (id int, name varchar(50), respondents as dbo.CountRespondents(id))
insert into respondents values (1, 1)
insert into respondents values (2, 1)
insert into respondents values (3, 1)
insert into respondents values (4, 2)
insert into respondents values (5, 2)
insert into studies values (1, 'Study 1')
insert into studies values (2, 'Study 2')
select * from studies
EF代码
ctx.Studies.Property(s => s.Respondents).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);
而不是Include
,请使用Property
。
我无法确切地说这对你来说是否足够高效,因为我不知道音量 - 而且我还没有用我写的SQL来测试EF部分。但我认为它应该可以正常工作。
答案 1 :(得分:0)
http://msdn.microsoft.com/en-us/data/jj574232.aspx
有时知道有多少实体与数据库中的另一个实体相关,而实际上不会产生加载所有这些实体的成本。使用LINQ Count方法的Query方法可用于执行此操作。例如:
using (var context = new BloggingContext())
{
var blog = context.Blogs.Find(1);
// Count how many posts the blog has
var postCount = context.Entry(blog)
.Collection(b => b.Posts)
.Query()
.Count();
}