对实体框架进行多次插入会导致=>物理连接不可用
本文关键字:连接 框架 实体 插入 | 更新日期: 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在会话表中持久化数据
- 通过提供标识符作为额外参数 来调用过程
- 从会话表中删除数据(最好通过在操作时间之外运行的作业,因为删除对表的使用有很大的影响)