简单小查询上的Linq to SQL随机超时

时间:2018-12-10 16:51:46

标签: c# sql visual-studio linq-to-sql

我有一个非常独特的问题。我有一个本地数据库DatabaseModel.mdf,该数据库利用linq来实现sql类。有时,我会随机收到此错误:

  

System.Data.SqlClient.SqlException:'连接超时已过期。登录后阶段已过超时时间。等待服务器完成登录过程并做出响应时,连接可能已超时;或者尝试创建多个活动连接时可能已超时。尝试连接到该服务器所花费的时间为-[登录前]初始化= 26;握手= 11; [登录]初始化= 4;认证= 4; [登录后]完成= 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条记录。我在互联网和SO上搜寻了几个月,试图找到在发布之前遇到相同问题的人,但无济于事。任何人有任何想法吗?

更新

所以我将问题缩小了一点,这似乎仅在调试模式下发生。如果我运行单元测试,它可以正常工作,但是,如果我调试单元测试,有时会得到错误,有时却不会。也许会有所帮助。

1 个答案:

答案 0 :(得分:0)

经过一番梳理和深思熟虑后,我想出了解决我问题的方法。我在回答自己的问题,以防万一其他人遇到这个问题,他们不必经历我经历的一切。

我注意到在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(); }
    }
}

然后让我震惊:如果问题不是由代码引起的,而是由调试本身引起的,怎么办?就像我说的那样,问题在我不进行调试时就消失了,几乎就像一个反向的heisenbug。所以我测试了它。我以调试模式运行了单元测试,并断断续续地断断续续地尝试尝试重现该问题。没有错误。再运行一次,然后离开计算机。回来,当我从断点继续调试会话时,错误浮出水面。

然后,我进行了单元测试,并有意在该断点处等待了30秒。 每次都将异常抛出失败。

因此,基本上我的假设是,如果代码暂停并且您打开了连接,则计时器停止。 不是。计时器在暂停期间超时,然后当我继续会话时,它已经有了等待我的异常。这确实让我感到惊讶,这是我什至没有想到的,因为我无法在互联网或文档中找到任何表明其为预期行为的内容。

我希望这对遇到此问题的所有人有所帮助。