我将首先总结我的问题,然后提供大量细节和我已经尝试过的方法。
总结:
我有一个内部 winform 应用程序,它使用 Linq 2 Sql 连接到本地 SQL Express 数据库。每个用户都有自己的数据库,数据库通过合并复制与中央数据库保持同步。所有数据库都是 SQL 2005(sp2or3)。我们已经使用这个应用程序 5 个多月了,但最近我们的用户收到 Timeout expired。操作完成前超时时间已过或服务器未响应。
详细:
奇怪的是,他们在两个不同的位置(2 种不同的 LINQ 方法)得到了它,并且只在给定的时间段内第一次触发(~5 分钟) .
一种 LINQ 方法是提取与 FK ID 匹配的所有记录,然后操纵它们以形成 TreeView 的层次结构 View 。第二个是提取与 FK ID 匹配的所有记录并将它们转储到 DataGridView 中。我唯一能找到的与 2 的共同点是第一个是 IEnumerable,第二个从 IQueryable -> IEnumerable -> DataTable... 转换自身。
我在 Profiler 中查看了查询,它们“看起来”很正常。它们不是很复杂的查询。他们只从一张表中拉回 10 - 90 条记录。
任何想法、建议、暗示都将不胜感激。我对此束手无策....
public IList<CaseNoteTreeItem> GetTreeViewDataAsList(int personID)
{
var myContext = MatrixDataContext.Create();
var caseNotesTree =
from cn in myContext.tblCaseNotes
where cn.PersonID == personID
orderby cn.ContactDate descending,
cn.InsertDate descending
select new CaseNoteTreeItem
{
CaseNoteID = cn.CaseNoteID,
NoteContactDate = Convert.ToDateTime(cn.ContactDate).
ToShortDateString(),
ParentNoteID = cn.ParentNote,
InsertUser = cn.InsertUser,
ContactDetailsPreview = cn.ContactDetails.Substring(0, 75)
};
return caseNotesTree.ToList<CaseNoteTreeItem>();
}
还有这个
public static DataTable GetAllCNotes(int personID)
{
using (var context = MatrixDataContext.Create())
{
var caseNotes =
from cn in context.tblCaseNotes
where cn.PersonID == personID
orderby cn.ContactDate
select new
{
cn.ContactDate,
cn.ContactDetails,
cn.TimeSpentUnits,
cn.IsCaseLog,
cn.IsPreEnrollment,
cn.PresentAtContact,
cn.InsertDate,
cn.InsertUser,
cn.CaseNoteID,
cn.ParentNote
};
return caseNotes.ToList().CopyLinqToDataTable();
}
}
编辑以显示生成的 SQL
这是GetTreeViewAsList(int personID)
SELECT [t0].[CaseNoteID], [t0].[ParentNote] AS [ParentNoteID], CONVERT(DateTime,[t0].[ContactDate]) AS [value], [t0].[InsertUser], SUBSTRING([t0].[ContactDetails], 0 + 1, 75) AS [ContactDetailsPreview]
FROM [dbo].[tblCaseNotes] AS [t0]
WHERE [t0].[PersonID] = 123456
ORDER BY [t0].[ContactDate] DESC, [t0].[InsertDate] DESC
这是 GetALLCaseNotes(int personID)
SELECT [t0].[ContactDate], [t0].[ContactDetails], [t0].[TimeSpentUnits], [t0].[IsCaseLog], [t0].[IsPreEnrollment], [t0].[PresentAtContact], [t0].[InsertDate], [t0].[InsertUser], [t0].[CaseNoteID], [t0].[ParentNote]
FROM [dbo].[tblCaseNotes] AS [t0]
WHERE [t0].[PersonID] = 123456
ORDER BY [t0].[ContactDate]
最佳答案
PersonId 上缺少索引意味着这两个问题查询都需要进行全表扫描。当数据不在缓冲区中时,这意味着大量 I/O,这解释了为什么您会注意到它,特别是在给定时间段内它们第一次触发时。
添加以下索引应该可以解决它。
CREATE NONCLUSTERED INDEX ix_tblCaseNotes_PersonID ON tblCaseNotes (PersonID)
关于c# - 缓冲区缓存清理时出现“超时已过期”错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2951024/