我的方法看起来像这样:
private static IEnumerable<OrganizationViewModel> GetOrganizations()
{
var db = new GroveDbContext();
var results = db.Organizations.Select(org => new OrganizationViewModel
{
Id = org.OrgID,
Name = org.OrgName,
SiteCount = org.Sites.Count(),
DbSecureFileCount = 0,
DbFileCount = 0
});
return results;
}
这很快就会返回结果。
但是,您会注意到OrganizationViewModel必须具有设置为“0”的属性。组织模型中有一些属性,我通过部分类添加并使用[NotMapped]进行修饰:UnsecureFileCount和SecureFileCount。
如果我将这些0改为有用的东西......
DbSecureFileCount = org.SecureFileCount,
DbFileCount = org.UnsecureFileCount
...我得到“仅支持初始化器,实体成员和实体导航属性”例外。我发现这有点令人困惑,因为我觉得我不是在问数据库,我只是设置了视图模型的属性。
然而,由于EF没有听我的论点,我尝试了另一种方法:
private static IEnumerable<OrganizationViewModel> GetOrganizations()
{
var db = new GroveDbContext();
var results = new List<OrganizationViewModel>();
foreach (var org in db.Organizations)
{
results.Add(new OrganizationViewModel
{
Id = org.OrgID,
Name = org.OrgName,
DbSecureFileCount = org.SecureFileCount,
DbFileCount = org.UnsecureFileCount,
SiteCount = org.Sites.Count()
});
}
return results;
}
从技术上讲,这给了我正确的结果,没有例外,但它需要永远。 (“永远”我的意思是超过60秒,而第一个版本在一秒钟内提供结果。)
有没有办法优化第二种方法?或者有没有办法让第一种方法起作用?
答案 0 :(得分:0)
另一种选择是将值作为匿名类型加载回来,然后循环加载你的viewmodel(n + 1很可能是缓慢的原因)。
例如:
var results = db.Organizations.Select(org => new
{
Id = org.OrgID,
Name = org.OrgName,
DbSecureFileCount = org.SecureFileCount,
DbFileCount = org.UnsecureFileCount,
SiteCount = org.Sites.Count()
}).ToList();
var viewmodels = results.Select( x=> new OrganizationViewModel
{
Id = x.Id,
Name = x.Name,
DbSecureFileCount = x.DbSecureFileCount,
DbFileCount = x.DbFileCount,
SiteCount = x.SiteCount
});
抱歉格式化;我正在打电话。
答案 1 :(得分:0)
在循环的每次迭代中,你基本上都是懒惰加载每个对象,导致n + 1个查询。
你应该做的是将整个集合带入内存,并从那里使用它。
示例代码:
var organizationList = db.Organizations.Load();
foreach (var org in organizationList.Local)
{
//Here you are free to do whatever you want
}