烦人的SQLexception,可能是由于某些代码做错了

我开始研究这个“已经开始”的项目,在尝试执行与SQL Server 2008的一些交互时,我遇到了一个非常烦人的错误:

服务器无法恢复事务。 说明:

我在这个特定方法调用中遇到的其中一个错误:

aspx.cs调用:

busProcesso openProcess = new busProcesso(pProcessoId); try { if (openProcess.GetDocument() == null) { //Irrelevant code. } } catch{ //... } 

商务舱(相关部分):

  public class busProcesso : IbusProcesso { public Processo vProcesso { get; set; } RENDBDataContext db; public busProcesso() { vProcesso = new Processo(); } public busProcesso(decimal pProcessoId) { db = new RENDBDataContext(); try { vProcesso = db.Processos.SingleOrDefault(x => x.Id == pProcessoId); } catch (Exception ex) { throw new Exception(ex.Message, ex); } } public string GetDocument() { try { string document = null; foreach (Processo_has_Servico ps in ListaServicosProcesso()) { if (ps.Servico.Document != null) //Get the error right at this line. { document = ps.Servico.Document; } } return document ; } catch (Exception ex) { throw new Exception(ex.Message, ex); } } public IQueryable ListaServicosProcesso() { db = new RENDBDataContext(); try { return from ps in db.Processo_has_Servicos join s in db.Servicos on ps.Servico_Id equals s.Id where ps.Processo_Id == vProcesso.Id select ps; } catch (Exception ex) { throw new Exception(ex.Message, ex); } } } 

正如我所说,错误发生在这一行:

来自GetDocument()方法的if (ps.Servico.Document != null)

打开SQL Server Activity Monitor ,我看到我的数据库有一个进程(.Net SqlClient Data Provider)

经过一段时间/使用(当我开始得到“服务器无法恢复事务”错误时),我转到SQL Server活动监视器,并且还有大约5或6个相同的进程没有被杀死(可能)应该’去过。 当我手动杀死它们时,错误会停止一段时间,直到它再次启动。

我并不擅长在OO和所有人工作 ,所以我可能会遗漏一些东西,也许某种方式来关闭其中一个连接。 此外,欢迎任何有关此结构的帮助/提示。

PS。 每次都不会发生错误。 有时它运行得很完美。 然后它开始给出错误。 然后停止。 有时它只发生一次……非常奇怪。

ListaServicosProcesso中的代码正在创建上下文数据库。 然后它返回一个IQueryable。

此时没有向数据库发送任何请求。

然后在代码中有一个for。 此时,EF说“我需要从数据库中获取数据”。 所以它试图获取数据。

但是上下文db现在已经超出范围,因此它会在尝试使用数据的第一行崩溃。

有两种方法可以解决这个问题:

  • 从ListaServicosProcesso返回一个列表,这将强制执行数据库调用
  • 将每个移动到ListaServicosProcesso

编辑

Pharabus是正确的db不在范围之外。 问题出在这里:

  db = new RENDBDataContext(); 

正在创建一个新的上下文实例,而不会丢弃旧的实例。 尝试在ListaServicosProcesso的末尾处理db。 甚至更好地将db放在using语句中。 但是必须在fore语句中移动foreach。

这里有几个想法。

1 /您可以附加SQL Server探查器以查看正在执行的查询,这将允许您复制并粘贴该查询以查看数据库中的数据。 这可能会有所帮助。

2 /你永远不会检查ps.Servico是否为null – 你直接跳到ps.Servico.Document 。 如果ps.Servico为null,那么如果尝试访问该对象的任何属性,则会得到空引用exception。

我不确定你所看到的错误的确切原因(如果你谷歌它,引用到处都是……),但你可以在代码中改进一些东西, 我已经发现只是经常清理东西会让问题消失 。 不总是 ,但经常。

我同意其他的回答者说,这将有助于更好地跟踪您的DataContext。 例如,您在构造函数中创建了一次,然后ListaServicosProcesso()创建它。 那时vProcesso在一个DataContext上,而其他实体将在另一个上,这会变得混乱。

我想你可以简化整个事情,例如你可以像这样组合GetDocument()ListaServicosProcesso()

 public string GetDocument() { try { // Are you sure vProcesso is not null? if (vProcesso == null) return null; // Only create the context if it wasn't already created, if (db == null) db = new RENDBDataContext(); return db.Processo_has_Servicos .Where(ps => ps.Processo_Id == vProcesso.Id && ps.Servico.Document != null) .Select(ps => ps.Servico.Document) // use an implicit join .SingleOrDefault(); } catch (Exception ex) { throw new Exception(ex.Message, ex); } }