使用实体框架执行许多插入会导致=>物理连接不可用

时间:2015-10-08 10:06:52

标签: c# sql-server entity-framework stored-procedures

我使用最新的实体框架,并通过存储过程插入大约425000个实体。

然后发生异常。它仍然插入了32766个实体。

代码

using (var context = new MyContext())
{
    foreach (var item in attributes)
    {
        CreateAttribute(item.productXml, item.NewProduct, context);
    }
}

private static void CreateAttribute(XmlProduct xmlProduct, ProductBase newProdB, MyContext context)
{
    foreach (string attribute in xmlProduct.Properties.Keys)
    {
        double doubleValue;
        if (double.TryParse(xmlProduct.Properties[attribute], out doubleValue))
        {
            //if cast fails
            context.app_sp_AddAttribute(attribute, doubleValue, null, newProdB.ID);
        }
        else
        {
            context.app_sp_AddAttribute(attribute, null, xmlProduct.Properties[attribute], newProdB.ID);
        }
    }
}

错误

A transport-level error has occurred when receiving results from the server. (provider: Session Provider, error: 19 - Physical connection is not usable)

如何修复该错误?

更新

public virtual ObjectResult<Nullable<int>> app_sp_AddAttribute(string attributeName, Nullable<double> numericValue, string stringValue, Nullable<int> productID)
{
    var attributeNameParameter = attributeName != null ?
        new ObjectParameter("AttributeName", attributeName) :
        new ObjectParameter("AttributeName", typeof(string));

    var numericValueParameter = numericValue.HasValue ?
        new ObjectParameter("NumericValue", numericValue) :
        new ObjectParameter("NumericValue", typeof(double));

    var stringValueParameter = stringValue != null ?
        new ObjectParameter("StringValue", stringValue) :
        new ObjectParameter("StringValue", typeof(string));

    var productIDParameter = productID.HasValue ?
        new ObjectParameter("ProductID", productID) :
        new ObjectParameter("ProductID", typeof(int));

    return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<Nullable<int>>("app_sp_AddAttribute", attributeNameParameter, numericValueParameter, stringValueParameter, productIDParameter);
}

异常发生在return语句!

An unhandled exception of type 'System.Data.Entity.Core.EntityCommandExecutionException' occurred in EntityFramework.SqlServer.dll

堆栈跟踪:

 at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at System.Data.SqlClient.TdsParserStateObject.ReadSniError(TdsParserStateObject stateObj, UInt32 error)
   at System.Data.SqlClient.TdsParserStateObject.ReadSniSyncOverAsync()
   at System.Data.SqlClient.TdsParserStateObject.TryReadNetworkPacket()
   at System.Data.SqlClient.TdsParserStateObject.TryPrepareBuffer()
   at System.Data.SqlClient.TdsParserStateObject.TryReadByte(Byte& value)
   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
   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, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds, Boolean describeParameterEncryptionRequest)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite)
   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(CommandBehavior behavior)
   at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.<Reader>b__c(DbCommand t, DbCommandInterceptionContext`1 c)
   at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget target, Func`3 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed)
   at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.Reader(DbCommand command, DbCommandInterceptionContext interceptionContext)
   at System.Data.Entity.Internal.InterceptableDbCommand.ExecuteDbDataReader(CommandBehavior behavior)
   at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
   at System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior)

{"A transport-level error has occurred when receiving results from the server. (provider: Session Provider, error: 19 - Physical connection is not usable)"}

1 个答案:

答案 0 :(得分:0)

基于ewahner的建议并对错误原因进行小规模研究,它主要与Sql Server限制有关(从服务器读取日志可能会给出一些提示)并且一个可能的解决方案是使用批量插入。我在一个项目中使用了这个extension,结果非常好(比添加实体的经典EF保存快几十倍)。

如果您的存储过程很复杂(进行一些计算,在其他表中保留一些数据等),您仍然可以使用批量插入:

  • 生成标识符(插入会话标识符)
  • 使用生成的标识符作为批处理标识符
  • ,通过BulkInsert将数据保存在会话表中
  • 通过提供标识符作为额外参数来调用该过程
  • 从会话表中删除数据(更好地通过在营业时间以外运行的作业,因为删除会对表使用产生很大影响)