定期InvalidCastException的和“服务器无法恢复交易”使用LINQ(Periodic

2019-07-05 09:08发布

I see this on our stage system, after it has been up for 2-3 days.

"The server failed to resume the transaction. Desc:39000000ef." (with desc:xxx increasing every time).

The stack trace shows

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 ...

After this has happened the entire server goes to heck. It seems like the metadata is no longer correctly represented in memory, because I see many InvalidCastExceptions afterwards. I'm guessing this is due to the system trying to deserialize a string into an int field because the metadata is offset incorrectly.

i.e.

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)

What does this mean?

I'm fairly sure the database wasn't updated behind the systems back, and the database was online the entire time.

The problem persists from here on out, until the server is restarted, after which everything works nicely.

Do I need to have code that re-establishes database connection if it fails? Doesn't the framework handle this by itself?

I'm using Sql server 2008, IIS 6, and .Net 3.5SP1

UPDATE: The code structure does something like this:

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();
    }
}

Answer 1:

这可能不是你的代码有问题。 这是在SQL Server中的错误。 他们曾在SQL Server 2005中类似的问题这仅仅只是合适的条件下发生的,所以很少有人见过它,那些确实是非常困惑。

话虽如此,这里有一些事情要检查有同样的问题,努力为别人:

  • 寻找那些未关闭的DataReader。 请确保你在做myReader.Close()后,你读你想要的行。 很多人只是岩石上,而不关闭。
  • 使用本机的SqlTransaction类,而不是OleDbTransactions的尽可能。
  • 看看你的交易。 请确保您提交/回滚干净您关闭连接之前。
  • 使用Connection.BeginTransation而不是Connection.BeginDbTransaction


Answer 2:

  • 不要共用不同的操作中相同的DataContext。 使用相同的DataContext到组的一组操作,你会被提交。 如果您有另一组,你将另行提交使用单独的DataContext。
  • 我不知道,还要检查一下,如果你在同一时间枚举超过2个IQueryables。 如果是这样的话,请尝试使用一个单独的DataContext第二枚举,以确保它不被LINQ2SQL试图在同一时间打开给读者造成的。
  • 确保你的模型是最新的,与你的数据库。 该结构在LINQ2SQL设计师定义不会自动更新,所以当你添加一个字段,你需要确保了加设计师(也许是重新添加表,如果你还没有改名的任何字段)。


Answer 3:

只是一个更新:

  • 我找到的bug我们使用通过直接数据源到报表服务器LINQ2SQL实体的。

即我们正在做这样的事情:

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

出于某种原因,这使DataContext的困惑,在相同的应用程序域运行时也是如此。



Answer 4:

你使用工作的原子单位DataContext对象? 这将与连接问题很多帮助,如果存在。

也有时你需要检查在RAM例如物理伤害。



文章来源: Periodic InvalidCastException and “The server failed to resume the transaction” with Linq