0

我有一个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 让它变得简单……这显然是有代价的。

请原谅和滥用的术语。

4

3 回答 3

0

我的建议:

  1. 确保您的数据库索引已正确调整。无论您如何生成查询 SQL,没有正确索引的连接都会影响您的性能。如果您使用的是 SQL Server,这很容易使用数据库引擎优化顾问。对于初学者,一般规则是外键列应该被索引。
  2. 考虑用普通的旧 SQL 编写这个关键路径查询。在您研究 Entity Framework 的短时间内,您已经掌握了很多关于 Entity Framework 的技巧,我相信可能有一种方法可以优化您所做的工作,但肯定是加快这一进程的有效方法up是绕过ORM层。
于 2013-06-07T05:58:53.700 回答
0

我选择切换到延迟加载,这将加载时间减少了 70%。我意识到这并不理想,因为有更多的数据库往返,但如果网站增长,那么我会担心它。不理想,但我最初更关心性能。所以总而言之,我做了以下事情

添加virtual到导航属性。删除了几乎所有超重查询的包含

结果是 2.5 秒的加载时间而不是 15 秒(基于浏览器时间线而不是 sql 分析器)。

于 2013-06-10T16:01:27.023 回答
-1

在我的项目中,我创建了使用 EF 的存储库,所以我写如下

  public IQueryable<Company> Companies
    {
        get
        {
            return context.Companies.Include("BankAccounts").Include("CompanyContacts").Include("MyClients").Include("MyCompanies").Include("Address");
        }
    }

现在我可以在我的代码中的任何地方调用 Companies 而无需包含。

CompanyRepository comrep = new CompanyRepository();
var companies = comrep.Companies(c=>c.FullName == "Made in Azerbaijan").SingleOrDefault();

我希望这能帮到您

于 2013-06-07T05:40:08.417 回答