Случайные тайм-ауты Linq to SQL для простых небольших запросов - PullRequest
0 голосов
/ 10 декабря 2018

У меня довольно уникальная проблема.У меня есть локальная база данных DatabaseModel.mdf, которая использует классы linq to sql.Иногда, случайно, я получаю эту ошибку:

System.Data.SqlClient.SqlException: 'Время ожидания подключения истекло.Время ожидания истекло на этапе после входа в систему.Возможно, истекло время ожидания соединения, пока сервер завершит процесс входа в систему и ответит;Или это могло быть превышено время ожидания при попытке создать несколько активных соединений.Длительность попытки подключения к этому серверу составила - [Pre-Login] initialization = 26;квитирование = 11;[Логин] инициализация = 4;Аутентификация = 4;[Post-Login] завершено = 1007;'

Вот минимальная изоляция используемого кода:

public class Universe : RepositoryObject
{
    public int ID { get; private set; } = -1;
    public string Name { get; set; }

    public static List<Universe> All()
    {
        using (LinqModelDataContext context = new LinqModelDataContext(Model.DatabaseConnection))
        {
            List<Universe> universes = new List<Universe>();
            foreach (UniverseModel model in context.UniverseModels)
            {
                Universe universe = PopulateUniverse(model);
                if (!(universe is null)) { universes.Add(universe); }
            }
            return universes.Count == 0 ? null : universes;
        }
    }

    public override void Save()
    {
        using (LinqModelDataContext context = new LinqModelDataContext(Model.DatabaseConnection))
        {
            UniverseModel model = context.UniverseModels.FirstOrDefault(x => x.Id == this.ID);
            if (model is null)
            {
                model = new UniverseModel()
                {
                    Name = this.Name
                };
                context.UniverseModels.InsertOnSubmit(model);
            }
            else
            {
                model.Name = this.Name;
            }

            context.SubmitChanges();
            this.ID = model.Id;         //! Gives back the ID that SQL assigned to the record.
            this.IsSaved = true;
        }
    }

    private static Universe PopulateUniverse(UniverseModel model)
    {
        if (model is null) { return null; }
        return new Universe()
        {
            ID = model.Id,
            Name = model.Name
        };
    }
}

А затем модульный тест:

    [TestMethod]
    public void AllMethodProperlyReturnsAllInstances()
    {
        // Arrange
        Model.PopulateDatabaseConnection(GlobalTestData.TestingDirectory);
        List<Universe> universes = new List<Universe>();
        universes.Add(new Universe() { Name = "Test1" });
        universes.Add(new Universe() { Name = "Test2" });
        universes.Add(new Universe() { Name = "Test3" });

        // Act
        universes.ForEach(x => x.Save());
        List<Universe> returnUniverses = Universe.All();

        // Assert
        foreach (Universe universe in universes)
        {
            if (!returnUniverses.Any(x => x.ID == universe.ID)) { Assert.Fail(); }
        }
    }

Я не хочуприбегнуть к установке тайм-аута команды, потому что соединение не должно занимать так много времени для 10 записей.Я искал интернет и ТАК в течение многих месяцев, пытаясь найти кого-то, у кого была та же самая проблема прежде, чем я отправлю, но безрезультатно.У кого-нибудь есть идеи?

Обновление

Так что я немного сузил проблему, кажется, это происходит только в режиме отладки.Если я запускаю модульный тест, он работает нормально, но если я отлаживаю модульный тест, иногда я получаю ошибку, а иногда нет.Может быть, это немного поможет.

1 Ответ

0 голосов
/ 10 декабря 2018

После нескольких сессий, посвященных уходу за волосами и глубоким размышлениям, я нашел решение своей проблемы.Я отвечаю на свой вопрос только на тот случай, если кто-нибудь еще столкнется с этой проблемой, им не придется проходить через то, что я прошел.

Я заметил, что установка точки останова на методе Save сделалапроблема более вероятна:

[TestMethod]
public void AllMethodProperlyReturnsAllInstances()
{
    // Arrange
    Model.PopulateDatabaseConnection(GlobalTestData.TestingDirectory);
    List<Universe> universes = new List<Universe>();
    universes.Add(new Universe() { Name = "Test1" });
    universes.Add(new Universe() { Name = "Test2" });
    universes.Add(new Universe() { Name = "Test3" });

    // Act
    universes.ForEach(x => x.Save()); // <-- Break Point Here
    List<Universe> returnUniverses = Universe.All();

    // Assert
    foreach (Universe universe in universes)
    {
        if (!returnUniverses.Any(x => x.ID == universe.ID)) { Assert.Fail(); }
    }
}

Тогда меня поразило: что, если проблема вызвана не кодом, а самой отладкой?Как я уже говорил, проблема исчезла, когда я не отлаживал, почти как обратный гейзенбаг.Итак, я проверил это.Я запускал модульное тестирование в режиме отладки с точкой прерывания снова и снова в быстрой последовательности, чтобы попытаться воспроизвести проблему.Нет ошибокЗапустил его еще раз, а затем отошел от компьютера.Вернулся, и когда я продолжил сеанс отладки с точки останова, всплыла ошибка.

Затем я запустил модульное тестирование и намеренно ждал в этой точке останова в течение 30 секунд. Он генерировал исключение каждый раз без сбоев.

Так что с моей стороны было предположение, что если код остановлен и у вас открыто соединение, таймер останавливается. Это не так.Таймер истекал во время остановки, а затем, когда я продолжил сеанс, меня уже ожидало исключение. Это было для меня действительно сюрпризом, и я даже не подумал об этом, потому что могне найти ничего в интернете или документации, где говорится, что это ожидаемое поведение.

Надеюсь, это поможет любому, кто столкнется с этой проблемой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...