对实体框架进行多次插入会导致=>物理连接不可用

本文关键字:连接 框架 实体 插入 | 更新日期: 2023-09-27 18:16:54

我使用最新的实体框架,并通过存储过程插入了大约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);
}

异常发生在返回语句处!

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)"}

对实体框架进行多次插入会导致=>物理连接不可用

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

如果您的存储过程很复杂(需要进行一些计算,在其他表中持久化一些数据等),您仍然可以使用Bulk insert:

  • 生成标识符(插入会话标识符)
  • 使用生成的标识符作为批处理标识符,通过BulkInsert在会话表中持久化数据
  • 通过提供标识符作为额外参数
  • 来调用过程
  • 从会话表中删除数据(最好通过在操作时间之外运行的作业,因为删除对表的使用有很大的影响)