Ошибка «Тайм-аут истек», когда буферный кэш очищен - PullRequest
2 голосов
/ 01 июня 2010

Сначала я подведу итог своей проблемы, а затем предложу подробные сведения и то, что уже попробовал.

Резюме:

У меня есть внутреннее приложение winform, которое использует Linq 2 Sql для подключения к локальной базе данных SQL Express. У каждого пользователя есть своя БД, и она остается синхронизированной посредством репликации слиянием с центральной БД. Все БД являются SQL 2005 (sp2or3). Мы используем это приложение уже более 5 месяцев, но в последнее время наши пользователи получают Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.

Детальнее:

Странно то, что они получают это в двух разных местах ( 2 разных метода LINQ ) и только в первый раз, когда они запускаются за определенный период времени ( ~ 5 минут ).

Один метод LINQ извлекает все записи, которые соответствуют идентификатору FK, а затем управляет ими, чтобы сформировать представление Heirarchy для TreeView. Второй - извлечение всех записей, соответствующих идентификатору FK, и сброс их в DataGridView. Единственное, что я могу найти общего с этими двумя, это то, что первый является IEnumerable, а второй преобразуется из IQueryable -> IEnumerable -> DataTable ...

Я посмотрел на запросы в Профилировщике, и они «казались» нормальными. Это не очень сложные запросы. Они извлекают только 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]

Ответы [ 2 ]

1 голос
/ 02 июня 2010

Отсутствие индекса PersonId означает, что оба проблемных запроса должны выполнить полное сканирование таблицы. Когда данные уже не находятся в буфере, это означает большое количество операций ввода-вывода, что объясняет, почему вы замечаете это, особенно при первом запуске за определенный период времени.

Добавление следующего индекса должно разрешить его.

CREATE NONCLUSTERED INDEX ix_tblCaseNotes_PersonID ON tblCaseNotes (PersonID)
1 голос
/ 01 июня 2010

Это немного далеко, но, возможно, проблема не в производительности, а в возможности подключения. Когда ваш SQL Server настроен на использование именованных каналов вместо протокола по умолчанию, может пройти много времени, прежде чем .NET SqlClient сможет установить соединение, поскольку он пытается установить соединение, используя порядок протокола по умолчанию.

Подробнее об этом можно прочитать здесь.

Удачи.

...