Entity framework 实体框架超时

Entity framework 实体框架超时,entity-framework,linq-to-sql,Entity Framework,Linq To Sql,在过去的几天里,我一直在想如何优化下面的查询,只是运气不太好。现在,我的测试数据库返回大约300条记录,其中嵌套数据很少,但是运行需要4-5秒,而且LINQ生成的SQL非常长(太长,无法包含在这里)。如有任何建议,将不胜感激 总结一下这个查询,我试图返回一个有点扁平化的当前状态的客户机列表的“快照”。一个参与方包含一个或多个具有角色的客户端(ASPNET角色提供程序),Journal返回参与方中所有客户端的最后1个日记条目,Task和LastLoginDate也是如此,因此使用OrderBy和F

在过去的几天里,我一直在想如何优化下面的查询,只是运气不太好。现在,我的测试数据库返回大约300条记录,其中嵌套数据很少,但是运行需要4-5秒,而且LINQ生成的SQL非常长(太长,无法包含在这里)。如有任何建议,将不胜感激

总结一下这个查询,我试图返回一个有点扁平化的当前状态的客户机列表的“快照”。一个参与方包含一个或多个具有角色的客户端(ASPNET角色提供程序),Journal返回参与方中所有客户端的最后1个日记条目,Task和LastLoginDate也是如此,因此使用OrderBy和FirstOrDefault函数

Guid userID = 'some user ID'
var parties = Parties.Where(p => p.BrokerID == userID).Select(p => new
{
ID = p.ID,
Title = p.Title,
Goal = p.Goal,
Groups = p.Groups,
IsBuyer = p.Clients.Any(c => c.RolesInUser.Any(r => r.Role.LoweredName == "buyer")),
IsSeller = p.Clients.Any(c => c.RolesInUser.Any(r => r.Role.LoweredName == "seller")),
Journal = p.Clients.SelectMany(c => c.Journals).OrderByDescending(j => j.OccuredOn).Select(j=> new 
    { 
        ID = j.ID,
        Title = j.Title,
        OccurredOn = j.OccuredOn,
        SubCatTitle = j.JournalSubcategory.Title
    }).FirstOrDefault(),
LastLoginDate = p.Clients.OrderByDescending(c=>c.LastLoginDate).Select(c=>c.LastLoginDate).FirstOrDefault(),
MarketingPlanCount = p.Clients.SelectMany(c => c.MarketingPlans).Count(),
Task = p.Tasks.Where(t=>t.DueDate != null && t.DueDate > DateTime.Now).OrderBy(t=>t.DueDate).Select(t=> new 
    {
        ID = t.TaskID,
        DueDate = t.DueDate,
        Title = t.Title
    }).FirstOrDefault(),
Clients = p.Clients.Select(c => new
    {
        ID = c.ID,
        FirstName = c.FirstName,
        MiddleName = c.MiddleName,
        LastName = c.LastName,
        Email = c.Email,
        LastLogin = c.LastLoginDate
    })
}).OrderBy(p => p.Title).ToList()

我认为发布SQL可以给我们一些线索,因为在投影之前或之后出现的OrderBy顺序之类的小事情可能会产生很大的不同

但无论如何,尝试在单独的查询中提取客户机,这可能会简化您的查询。然后在投影之前包括其他表,如日记和任务,并查看这对查询的影响:

//am not sure what the exact query would be, and project it using ToList() var clients = GetClientsForParty(); var parties = Parties.Include("Journal").Include("Tasks") .Where(p=>p.BrokerID == userID).Select( p => { .... //then use the in-memory clients IsBuyer = clients.Any(c => c.RolesInUser.Any(r => r.Role.LoweredName == "buyer")), ... } ) //我不确定确切的查询是什么,并使用ToList()进行投影 var clients=GetClientsForParty(); 风险值当事人=当事人。包括(“日记账”)。包括(“任务”) .Where(p=>p.BrokerID==userID)。选择(p=>{ .... //然后使用内存中的客户端 IsBuyer=clients.Any(c=>c.RolesInUser.Any(r=>r.Role.lowerdname==“买方”), ... } ) 在所有情况下,请安装并查看查询是如何受到影响的。EF可以安静的令人惊讶。类似于将OrderBy放在投影之前,对于所有这些FirstOrDefault或SingleOrDefault都是一样的,它们都会产生很大的影响

回到基础,如果您正在搜索LoweredRoleName,那么请确保它已被索引,以便查询速度更快(即使这可能是无用的,因为EF可能最终没有使用覆盖索引,因为它正在查询许多其他列)

另外,由于这是一个查看数据的查询(您不会更改数据),所以不要忘记关闭实体跟踪,这也会提高您的性能

最后,不要忘记,您可以直接编写SQL查询并将其投影到视图模型而不是匿名类型(我认为这是一个很好的实践),因此创建一个名为PartyViewModel的类,该类包含您要使用的展平视图,并将其与手工编制的SQL一起使用

//use your optimized SQL query that you write or even call a stored procedure db.Database.SQLQuery("select * from .... join .... on"); //使用您编写甚至调用存储过程的优化SQL查询 SQLQuery(“select*from….join….on”); 我正在围绕EF写一篇关于这些问题的文章。这篇文章还没有完成,但总而言之,耐心一点,使用这些技巧,观察它们的效果(并测量),你就会达到你想要的