Faire beaucoup d'insertions avec un framework d'entité aboutit à => La connection physique n'est pas utilisable

J'utilise le dernier framework d'entité et j'insère environ 425000 entités via une procédure stockée.

Puis une exception se produit. Il a quand même inséré 32766 entités.

Code

using (var context = new MyContext()) { foreach (var item in atsortingbutes) { CreateAtsortingbute(item.productXml, item.NewProduct, context); } } private static void CreateAtsortingbute(XmlProduct xmlProduct, ProductBase newProdB, MyContext context) { foreach (ssortingng atsortingbute in xmlProduct.Properties.Keys) { double doubleValue; if (double.TryParse(xmlProduct.Properties[atsortingbute], out doubleValue)) { //if cast fails context.app_sp_AddAtsortingbute(atsortingbute, doubleValue, null, newProdB.ID); } else { context.app_sp_AddAtsortingbute(atsortingbute, null, xmlProduct.Properties[atsortingbute], newProdB.ID); } } } 

Erreur

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

Comment puis-je corriger cette erreur?

METTRE À JOUR

 public virtual ObjectResult<Nullable<int>> app_sp_AddAtsortingbute(ssortingng atsortingbuteName, Nullable<double> numericValue, ssortingng ssortingngValue, Nullable<int> productID) { var atsortingbuteNameParameter = atsortingbuteName != null ? new ObjectParameter("AtsortingbuteName", atsortingbuteName) : new ObjectParameter("AtsortingbuteName", typeof(ssortingng)); var numericValueParameter = numericValue.HasValue ? new ObjectParameter("NumericValue", numericValue) : new ObjectParameter("NumericValue", typeof(double)); var ssortingngValueParameter = ssortingngValue != null ? new ObjectParameter("SsortingngValue", ssortingngValue) : new ObjectParameter("SsortingngValue", typeof(ssortingng)); var productIDParameter = productID.HasValue ? new ObjectParameter("ProductID", productID) : new ObjectParameter("ProductID", typeof(int)); return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<Nullable<int>>("app_sp_AddAtsortingbute", atsortingbuteNameParameter, numericValueParameter, ssortingngValueParameter, productIDParameter); } 

L'exception arrive à la déclaration de return!

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

Trace de la stack:

  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, Ssortingng resetOptionsSsortingng) 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, Ssortingng method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Ssortingng method) at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, Ssortingng 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)"} 

Basé sur la suggestion d'ewahner et faisant une petite search sur la cause de l'erreur, il est principalement lié à une limitation Sql Server (lire le journal du server pourrait donner quelques conseils) et une solution possible serait d'utiliser un encart en vrac . J'ai utilisé cette extension dans un projet et les résultats étaient très bons (des douzaines de fois plus rapides que les EF classiques, sauf les entités ajoutées).

Si votre procédure stockée est complexe (effectue certains calculs, conserve certaines données dans d'autres tables, etc.), vous pouvez toujours utiliser l'insertion en masse:

  • générer un identifiant (un identifiant de session d'insertion)
  • persistez vos données via BulkInsert dans une table de session en utilisant l'identifiant généré comme identifiant de lot
  • appeler la procédure en fournissant l'identifiant en tant que paramètre supplémentaire
  • supprimer des données de la table de session (mieux via un travail qui s'exécute en dehors des heures de fonctionnement, car les suppressions ont un impact important sur l'utilisation de la table)