恼人的SQL异常,可能是由于某些代码做错了

时间:2010-10-13 21:02:41

标签: c# asp.net linq-to-sql sql-server-2008 oop

我开始研究这个“已经开始”的项目,在尝试与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<Processo_has_Servico> 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);
        }
    }
}

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

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

GetDocument()

打开SQL Server 活动监视器,我看到我的数据库有一个进程(.Net SqlClient Data Provider)

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

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

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

3 个答案:

答案 0 :(得分:3)

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

此时尚未向数据库发送任何请求。

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

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

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

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

修改

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

 db = new RENDBDataContext();

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

答案 1 :(得分:2)

以下是一些尝试的想法。

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

2 /你永远不会检查ps.Serviconull - 你直接跳到ps.Servico.Document。如果ps.Servico为null,那么如果您尝试访问该对象上的任何属性,则会得到一个空引用异常。

答案 2 :(得分:1)

我不确定您所看到的错误的确切原因(如果您使用谷歌,引用已经到位......),但您可以在代码中改进一些内容我发现只是稍微清理一下会让问题消失。不总是,但经常。

我同意其他的回答者说,这将有助于更好地跟踪您的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);
    }
}