我有一个非常独特的问题。我有一个本地数据库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上搜寻了几个月,试图找到在发布之前遇到相同问题的人,但无济于事。任何人有任何想法吗?
所以我将问题缩小了一点,这似乎仅在调试模式下发生。如果我运行单元测试,它可以正常工作,但是,如果我调试单元测试,有时会得到错误,有时却不会。也许会有所帮助。
答案 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秒。 每次都将异常抛出失败。
因此,基本上我的假设是,如果代码暂停并且您打开了连接,则计时器停止。 不是。计时器在暂停期间超时,然后当我继续会话时,它已经有了等待我的异常。这确实让我感到惊讶,这是我什至没有想到的,因为我无法在互联网或文档中找到任何表明其为预期行为的内容。
我希望这对遇到此问题的所有人有所帮助。