我有一个Activity
模型,可以从7种不同类型的模型中提取模型。这些模型也有它们的关系,活动源需要能够显示我想要的信息。这意味着我在查询中大约有20个包含。我只是这样做了8个月左右,我读过有关编译查询,存储过程以及所有这些内容可能会让我失望的内容。我还读到我可以将我的代码第一个模型更改为virtual
,以便它可以进行延迟加载,但是我担心如果我有大量用户,所有这些数据库调用都会终止我的网站
首先是模型
public class Activity
{
public int ActivityID { get; set; }
public int ActivityTypeID { get; set; }
public int ContributorID { get; set; }
public int UserID { get; set; }
public int? ProjectID { get; set; }
public int? ProjectDocID { get; set; }
public int? CommentID { get; set; }
public int? BookID { get; set; }
public int? BookReviewID { get; set; }
public DateTime DateCreated { get; set; }
public Comment Comment { get; set; }
public ProjectDoc ProjectDoc { get; set; }
public Project Project { get; set; }
public Book Book { get; set; }
public BookReview BookReview { get; set; }
public ActivityType ActivityType { get; set; }
[ForeignKey("ContributorID")]
public User Contributor { get; set; }
[ForeignKey("UserID")]
public User User { get; set; }
public ICollection<ActivityLike> ActivityLike { get; set; }
public ICollection<ActivityComment> ActivityComment { get; set; }
}
现在查询
var activity = db.Activities
.Include(i => i.Contributor.BookStatus)
.Include(i => i.ActivityType)
.Include(i => i.ActivityLike.Select(y => y.User))
.Include(i => i.ActivityComment.Select(y => y.User))
.Include(i => i.Project.ProjectFollower)
.Include(i => i.Project.View)
.Include(i => i.Project.ProjectType)
.Include(i => i.Project.User)
.Include(i => i.Project.ProjectTag.Select(v => v.Tag))
.Include(i => i.Project.ProjectCategory.Select(v => v.Category))
.Include(i => i.Project.ProjectCharacteristic.Select(v => v.Characteristic))
.Include(i => i.Project.ProjectDoc.Select(v => v.ProjectDocVote))
.Include(i => i.Project.ProjectDoc.Select(v => v.User))
.Include(i => i.Comment.User)
.Include(i => i.Book.Author)
.Include(i => i.Book.BookReview.Select(v => v.User))
.Include(i => i.Book.BookReview.Select(v => v.BookReviewVote))
.Include(i => i.Book.BookCharacteristic.Select(v => v.Characteristic))
.Include(i => i.Contributor.Followers)
.Where(u =>
u.Contributor.Followers.FirstOrDefault(x => x.FollowerID == WebSecurity.CurrentUserId) != null
)
.OrderByDescending(d => d.DateCreated)
.Skip(offset)
.Take(results)
.ToList();
这就像6600行SQL(或其他任何东西)。
第一次运行需要10-16秒。因为我使用Skip()
并使用jquery进行无限滚动,所以每次单个ajax调用首次需要10-12秒。因此,如果我每次获得10个结果并且有100个结果那么超过100秒的等待时间,这是非常糟糕的。现在,下次用户在短时间内访问该页面时,速度非常快。
那么我应该如何改进这个查询,你能否提供具体的方法并解释解决方案,因为我很难理解编译的查询,什么不能。我能够做到这一点的唯一原因是因为EF让它变得简单......这显然有成本。
请原谅并滥用行话。
答案 0 :(得分:0)
我的建议:
答案 1 :(得分:0)
我选择切换到延迟加载,这将加载时间减少了70%。我意识到这不是理想的,因为更多的数据库往返,但如果网站增长,那么我会担心它。不理想,但我最初更关注性能。总而言之,我做了以下
在导航属性中添加了virtual
。
删除了超重量查询中的几乎所有包含
结果是2.5秒加载时间而不是15秒(基于浏览器时间轴而不是sql profiler)。
答案 2 :(得分:-1)
在我的项目中,我创建了使用EF的存储库,所以我写了如下
public IQueryable<Company> Companies
{
get
{
return context.Companies.Include("BankAccounts").Include("CompanyContacts").Include("MyClients").Include("MyCompanies").Include("Address");
}
}
现在我可以在我的代码公司的每个地方打电话,但不包括。
CompanyRepository comrep = new CompanyRepository();
var companies = comrep.Companies(c=>c.FullName == "Made in Azerbaijan").SingleOrDefault();
我希望这会对你有所帮助