Раздражающее исключение SQL, возможно из-за неправильного выполнения кода - PullRequest
1 голос
/ 14 октября 2010

Я начал работать над этим «уже запущенным» проектом, и у меня возникла действительно досадная ошибка при попытке выполнить некоторые взаимодействия с 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 Activity Monitor , я вижу, что есть процесс для моей базы данных (поставщик данных .Net SqlClient)

Через некоторое время / использование (когда яначинаю получать сообщение об ошибке «серверу не удалось возобновить транзакцию»), я захожу к монитору активности SQL Server, и есть еще около 5 или 6 идентичных процессов, которые не были убиты и (вероятно) должны были быть.Когда я вручную их убиваю, ошибка на некоторое время останавливается, пока не запустится снова.

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

PS.Ошибка не происходит каждый раз.Иногда это работает просто отлично.Тогда это начинает давать ошибку.Тогда это останавливается.Иногда это случается только один раз ... довольно странно.

Ответы [ 3 ]

3 голосов
/ 14 октября 2010

Код в ListaServicosProcesso создает контекстную базу данных.Затем он возвращает IQueryable.

На данный момент в базу данных не было отправлено ни одного запроса.

Тогда для каждого кода есть код.В этот момент EF говорит: «Мне нужно получить данные из базы данных».Таким образом, он пытается получить данные.

Но контекстная база данных теперь выходит за рамки видимости, поэтому он вылетает, в первой строке, которая пытается использовать данные.

Есть 2 способаобойти это:

  • вернуть список из ListaServicosProcesso, это заставит вызов базы данных выполнить
  • переместить для каждого в ListaServicosProcesso

Редактировать

Фарабус правильный, БД не выходит за рамки.Проблема здесь:

 db = new RENDBDataContext();

Новый экземпляр контекста создается без удаления старого.Попробуйте избавиться от БД в конце ListaServicosProcesso.Еще лучше поместить db в оператор использования.Но тогда foreach должен быть перемещен внутри оператора using.

2 голосов
/ 14 октября 2010

Вот пара идей, которые можно попробовать.

1 / Вы можете присоединить профилировщик SQL-сервера, чтобы увидеть выполняемый запрос, что позволит вам скопировать и вставить этот запрос, чтобы просмотреть данные, которые находятся в базе данных. Это может помочь.

2 / Вы никогда не проверяете, является ли ps.Servico null - вы прыгаете прямо к ps.Servico.Document. Если ps.Servico равно нулю, вы получите исключение нулевой ссылки, если попытаетесь получить доступ к любым свойствам этого объекта.

1 голос
/ 14 октября 2010

Я не уверен в точной причине ошибки, которую вы видите (если вы Google, ссылки повсюду ...), но есть несколько вещей, которые вы можете улучшить в своем коде Я обнаружил, что простая чистка вещей часто устраняет проблемы . Не всегда , но часто.

Я согласен с другими ответчиками, что это поможет лучше отслеживать ваши DataContext (s). Например, если вы создаете его один раз в конструкторе, то снова в 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);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...