2014-03-07 44 views
0

我有一个关于2场景的性能问题,哪个会更快。Sql Server计算功能和内存列表之间的性能

选项#1

难道是更快地抢在内存中,使用C#所有的旅行报告列表中删除我不想要的,例如:

var travelReports = db.TravelReports.Include("ApprovalStatuses") 
      .Where(s => s.IsDeleted == false).ToList(); 
      travelReports.RemoveAll(s => s.Status == TravelReportStatus.Draft); 
      travelReports.RemoveAll(s => s.Status == TravelReportStatus.NeedsInformation); 

在这种情况下,状态将在模型上进行计算,使用NotMapped属性和getter,使用审批状态,如:

if (ApprovalStatuses.Count == 0) 
{ 
    return TravelReportStatus.Draft; 
} 
else if (JobRoles.All(j => ApprovalStatuses.Any(a => a.Role == j && a.Status == ApprovalStatus.Approved))) 
{ 
    return TravelReportStatus.Processed; 
} 
else if (ApprovalStatuses.Any(s => s.Status == ApprovalStatus.Denied)) 
{ 
    return TravelReportStatus.Denied; 
} 
else 
{ 
    return TravelReportStatus.PendingApproval; 
} 

选项#2 将一个函数我在S模式QL并呼叫列状态:

CREATE FUNCTION dbo.GetTravelReportStatus(@travelReportId int) 
RETURNS int 
AS 
-- Returns a Enum Int Value of the Status -- 
BEGIN 

DECLARE @value int; 
DECLARE @count int; 
DECLARE @isReject int = 0; 
SELECT @isReject = Count(*) FROM dbo.Approvals WHERE TravelReportId = @travelReportId and Status = 3; 
SELECT @count = Count(*) FROM dbo.Approvals WHERE TravelReportId = @travelReportId; 
SELECT @value = 
CASE 
WHEN @isReject > 0 THEN 3 
WHEN @isReject = 0 and @count = 0 THEN 1 
WHEN @isReject = 0 and @count > 0 and @count < 6 THEN 2 
WHEN @isReject = 0 and @count >= 6 THEN 4 
END; 
return @value; 
END; 


Sql("ALTER TABLE dbo.TravelReports ADD Status AS dbo.GetTravelReportStatus(Id)"); 

然后使用SQL和实体框架来仅获取具有我想要的状态的旅行报告。

var travelReports = db.TravelReports.Include("ApprovalStatuses") 
       .Where(s => s.Status == TravelReportStatus.PendingApproval || s.Status == TravelReportStatus.Processed || s.Status == TravelReportStatus.Denied) 
       .Where(s => s.IsDeleted == false).ToList(); 

旅行报告将持续增长,但大约4年后,它们将被移动到归档存储并不再存在于数据库中。

我的问题是将选项1或选项2提供给我最好的性能?每次我要求旅行报告时,选项2是否会打2个查询的数据库?因此,如果我返回一个用户25个旅行报告,我将打到数据库25^2次来计算状态,在codefirst EF中有没有办法阻止它?

+0

”在内存中抓取所有旅行报告列表并使用C#删除那些我不想要的列表会更快吗?“除非你的桌子非常小。 –

+0

我编辑了你的标题。请参阅:“[应该在其标题中包含”标签“](http://meta.stackexchange.com/questions/19190/)”,其中的共识是“不,他们不应该”。 –

+0

对不起,我会在将来看到:) –

回答

0

我不知道EF是否要打3次数据库,但如果是let子句就可以解决它,所以它只会打一次。

var travelReports = (from s in db.TravelReports.Include("ApprovalStatuses") 
        let status = s.Status 
        where (status == TravelReportStatus.PendingApproval || 
          status == TravelReportStatus.Processed || 
          status == TravelReportStatus.Denied) && 
          reports.IsDeleted == false 
        select reports).ToList(); 

重新创建使用方法语法而非查询语法let条款是更加困难的事情。您必须创建一个匿名类型来充当您的价值的容器。对于这个简单的查询来说,这并不难,但是对于更复杂的查询,使用查询语法可能会更容易。

var travelReports = db.TravelReports.Include("ApprovalStatuses") 
       .Select(s => new {Query = s, Status = s.Status}) //Project to a new object that has the status pre-calculated 
       .Where(s => s.Status == TravelReportStatus.PendingApproval || s.Status == TravelReportStatus.Processed || s.Status == TravelReportStatus.Denied) 
       .Select(s => s.Query) //flatten the object back out. 
       .Where(s => s.IsDeleted == false) 
       .ToList(); 

附:要找出EF将要生成的查询,只需在IQueryable对象上执行.ToString(),它将返回将要发送到服务器的SQL。 “

var travelReportsQuery = db.TravelReports.Include("ApprovalStatuses") 
       .Where(s => s.Status == TravelReportStatus.PendingApproval || s.Status == TravelReportStatus.Processed || s.Status == TravelReportStatus.Denied) 
       .Where(s => s.IsDeleted == false) 

var travelReportsQueryText = travelReportsQuery.ToString(); 
var travelReports = travelReportsQuery.ToList(); 
+0

谢谢我会检查toString!当我询问关于如何在服务器上增加额外的时间时,我的意思是关于表格上的计算字段,并且该函数将表格打到2次。为了在你所提出的查询中使用Status,虽然它需要EF中的字段,但我仍然不确定它是否是最好的性能。 –