Периодическое InvalidCastException и "Сервер не смог возобновить транзакцию" с Linq

Я вижу это на нашей сценической системе, после того, как она была в течение 2-3 дней.

"Сервер не смог возобновить транзакцию. Desc: 39000000ef." (с desc: xxx увеличивается каждый раз).

Трассировка стека показывает

System.Data.SqlClient.SqlException: The server failed to resume the transaction. Desc:39000000ef.
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
at System.Data.SqlClient.SqlDataReader.ConsumeMetaData()
at System.Data.SqlClient.SqlDataReader.get_MetaData()
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
at System.Data.Common.DbCommand.ExecuteReader()
at System.Data.Linq.SqlClient.SqlProvider.Execute(Expression query, QueryInfo queryInfo, IObjectReaderFactory factory, Object[] parentArgs, Object[] userArgs, ICompiledSubQuery[] subQueries, Object lastResult)
at System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(Expression query, QueryInfo[] queryInfos, IObjectReaderFactory factory, Object[] userArguments, ICompiledSubQuery[] subQueries)
at System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query)
at System.Data.Linq.DataQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at ...

После того, как это произошло, весь сервер идет к черту. Похоже, что метаданные уже не правильно представлены в памяти, потому что впоследствии я вижу много InvalidCastExceptions. Я предполагаю, что это связано с тем, что система пытается десериализовать строку в поле int, потому что метаданные неправильно смещены.

то есть.

System.InvalidCastException: Specified cast is not valid.
at System.Data.SqlClient.SqlBuffer.get_Int32()
at System.Data.SqlClient.SqlDataReader.GetInt32(Int32 i)
at Read_Order(ObjectMaterializer`1 )
at System.Data.Linq.SqlClient.ObjectReaderCompiler.ObjectReader`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)

Что это значит?

Я уверен, что база данных не была обновлена ​​позади систем, и база данных была в сети все время.

Проблема сохраняется здесь, пока сервер не перезагрузится, после чего все будет хорошо работать.

Нужно ли иметь код, который заново устанавливает соединение с базой данных, если он не работает? Разве каркас не обрабатывает это сам?

Я использую сервер Sql 2008, IIS 6 и .Net 3.5SP1

UPDATE: Структура кода делает что-то вроде этого:

var dc = new datacontext()
IList<someobject> objs = dc.GetAllItemsToProcess()
var dc2 = new datacontext();
 foreach( var o in objs ) {
    try {
         var o2 = dc2.someobjects.SingleOrDefault(x=>x.id = o.id);
          // do stuff to o2
         dc2.save();
   } catch() {
          // something failed so restart datacontext()
         dc2 = new datacontext();
    }
}

Ответ 1

Просто обновление:

  • Я отследил ошибку в использовании Linq2Sql-объектов, переданных в качестве источников данных непосредственно в Report Server.

т.е. мы делали что-то вроде этого:

List<Order> orderList = orderRepository.getOrders();
ReportViewer rv = new ReportViewer();
rv.LocalReport.DataSources.Add("OrderList", orderList);
rv.Render();

По какой-то причине это привело к тому, что datacontext запутался даже при работе в одном домене приложений.

Ответ 2

Вероятно, это не проблема с вашим кодом. Это ошибка в SQL Server. У них была аналогичная проблема в SQL Server 2005. Это произошло только в условиях, которые были в порядке, так что очень немногие люди когда-либо видели это, а те, которые были очень запутаны.

Сказав это, вот некоторые вещи, чтобы проверить, что работали для других с той же проблемой:

  • Ищите DataReaders, которые не являются закрыто. Убедитесь, что вы делаете myReader.Close() после того, как вы прочитали строки, которые вы хотите. Многие люди просто рок без закрытия.
  • Использовать собственный класс SqlTransaction вместо OleDbTransactions везде возможно.
  • Посмотрите на свои транзакции. Убедиться вы совершаете/откатываете назад перед тем, как закрыть свое соединение.
  • Используйте Connection.BeginTransation скорее чем Connection.BeginDbTransaction

Ответ 3

  • Не используйте один и тот же DataContext для разных операций. Используйте тот же DataContext для группировки набора операций, которые вы будете отправлять. Если у вас есть другой набор, который вы будете отправлять отдельно, используйте отдельный DataContext.
  • Я не уверен, но также проверяю, перечисляете ли вы более двух IQueryables одновременно. В этом случае попробуйте использовать отдельный DataContext для второго перечисления, чтобы убедиться, что он не вызван тем, что linq2sql пытается открыть для читателей в то же время.
  • Убедитесь, что ваша модель обновлена ​​с вашей БД. Структура, определяемая дизайнером Linq2sql, не обновляется автоматически, поэтому при добавлении поля вам нужно убедиться, что он добавлен в конструктор (возможно, путем повторного добавления таблицы, если вы не переименовали какие-либо поля).

Ответ 4

Используете ли вы объект DataContext для атомных единиц работы? это поможет много проблем с подключением, если они существуют.

также иногда вам нужно проверить физический урон в ОЗУ, например.