我有以下 LINQ to SQL 方法,该方法需要花费大量时间来执行,但SQL对应方法非常简单快速。我在LINQ部分做错了吗?我只是想在数据网格中返回一些数据以只读方式显示。
据我所知,如果该工具不合适,请不要使用它,因此我可以在这里进行SQL调用,但我想了解为什么存在这样的差异。
下面是LINQ,然后是它转储的SQL。
public static DataTable GetEnrolledMembers(Guid workerID)
{
using (var DB = CmoDataContext.Create())
{
var AllEnrollees = from enrollment in DB.tblCMOEnrollments
where enrollment.CMOSocialWorkerID == workerID || enrollment.CMONurseID == workerID
join supportWorker in DB.tblSupportWorkers on enrollment.EconomicSupportWorkerID
equals supportWorker.SupportWorkerID into workerGroup
from worker in workerGroup.DefaultIfEmpty()
select
new
{
enrollment.ClientID,
enrollment.CMONurseID,
enrollment.CMOSocialWorkerID,
enrollment.EnrollmentDate,
enrollment.DisenrollmentDate,
ESFirstName = worker.FirstName,
ESLastName = worker.LastName,
ESPhone = worker.Phone
};
var result = from enrollee in AllEnrollees.AsEnumerable()
where (enrollee.DisenrollmentDate == null || enrollee.DisenrollmentDate > DateTime.Now)
let lastName = BLLConnect.MemberLastName(enrollee.ClientID)
let firstName = BLLConnect.MemberFirstName(enrollee.ClientID)
orderby enrollee.DisenrollmentDate ascending , lastName ascending
select new
{
enrollee.ClientID,
LastName = lastName,
FirstName = firstName,
NurseName = BLLAspnetdb.NurseName(enrollee.CMONurseID),
SocialWorkerName = BLLAspnetdb.SocialWorkerName(enrollee.CMOSocialWorkerID),
enrollee.EnrollmentDate,
enrollee.DisenrollmentDate,
ESWorkerName = enrollee.ESFirstName + " " + enrollee.ESLastName,
enrollee.ESPhone
};
DB.Log = Console.Out;
return result.CopyLinqToDataTable();
}
}
和SQL:
SELECT [t0].[ClientID], [t0].[CMONurseID], [t0].[CMOSocialWorkerID], [t0].[EnrollmentDate], [t0].[DisenrollmentDate], [t1].[FirstName] AS [ESFirstName], [t1].[LastName] AS [ESLastName], [t1].[Phone] AS [ESPhone]
FROM [dbo].[tblCMOEnrollment] AS [t0]
LEFT OUTER JOIN [dbo].[tblSupportWorker] AS [t1] ON [t0].[EconomicSupportWorkerID] = ([t1].[SupportWorkerID])
WHERE ([t0].[CMOSocialWorkerID] = @p0) OR ([t0].[CMONurseID] = @p1)
-- @p0: Input UniqueIdentifier (Size = 0; Prec = 0; Scale = 0) [060632ee-be09-4057-b17b-2d0190d0ff74]
-- @p1: Input UniqueIdentifier (Size = 0; Prec = 0; Scale = 0) [060632ee-be09-4057-b17b-2d0190d0ff74]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.30729.4926
答案 0 :(得分:4)
添加AsEnumerable()
:
var result = from enrollee in AllEnrollees.AsEnumerable()
...
您强制要求完全评估第一个查询,并从数据库中提取每个记录(AllEnrollees)。
使用您的SQL语句,您将在服务器上执行所有过滤,这将更快。
答案 1 :(得分:1)
首先,我不认为你在比较苹果和苹果,你有很多BllConnect.Something调用第二个linq查询的选择。另外,你必须取出另一个答案中提到的AsEnumerable。
考虑下面的内容(假设您在db和/或linq2sql设计器中添加了相应的关系):
public static DataTable GetEnrolledMembers(Guid workerID)
{
using (var DB = CmoDataContext.Create())
{
var AllEnrollees = from enrollment in DB.tblCMOEnrollments
where enrollment.CMOSocialWorkerID == workerID
|| enrollment.CMONurseID == workerID
let w = enrollment.EconomicSupporterWorker
select new
{
enrollment.ClientID,
enrollment.CMONurseID,
enrollment.CMOSocialWorkerID,
enrollment.EnrollmentDate,
enrollment.DisenrollmentDate,
ESFirstName = w != null ? w.FirstName : null,
ESLastName = w != null ? w.LastName : null,
ESPhone = w != null ? w.Phone : null
};
var filteredEnrollees = AllEnrollees
.Where(e=> e.DisenrollmentDate == null || e.DisenrollmentDate > DateTime.Now);
//benchmark how much it delays if you do a .ToList until here
// ... when comparing the sql, run it on the same remote computer you are running this,
// so you take into account the time to transfer the data.
filteredEnrollees = filteredEnrollees
.OrderBy(e=> e.DisenrollmentData) // benchmark here again
.ThenBy(e=> BLLConnect.MemberLastName(enrollee.ClientID)); // prob. causing issues
var result = // do what you already had, but against filteredEnrollees and benchmark
// prob. issues with BllConnect.* and BllAspnetdb.* being called for each record /
// ... doesn't happen in sql side
DB.Log = Console.Out;
return result.CopyLinqToDataTable();
}
}