Hangfire - Win32Exception (258): The wait operation timed out - c#

I sometimes get the following exception, when a job gets executed:
System.Data.SqlClient.SqlException (0x80131904): Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
---> System.ComponentModel.Win32Exception (258): The wait operation timed out.
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
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)
at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite, String methodName)
at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
at Dapper.SqlMapper.ExecuteCommand(IDbConnection cnn, CommandDefinition& command, Action`2 paramReader)
at Dapper.SqlMapper.ExecuteImpl(IDbConnection cnn, CommandDefinition& command)
at Hangfire.SqlServer.SqlServerDistributedLock.Acquire(IDbConnection connection, String resource, TimeSpan timeout)
at Hangfire.SqlServer.SqlServerConnection.AcquireLock(String resource, TimeSpan timeout)
at Hangfire.DisableConcurrentExecutionAttribute.OnPerforming(PerformingContext filterContext)
at Hangfire.Profiling.ProfilerExtensions.InvokeAction[TInstance](InstanceAction`1 tuple)
at Hangfire.Profiling.SlowLogProfiler.InvokeMeasured[TInstance,TResult](TInstance instance, Func`2 action, String message)
at Hangfire.Profiling.ProfilerExtensions.InvokeMeasured[TInstance](IProfiler profiler, TInstance instance, Action`1 action, String message)
at Hangfire.Server.BackgroundJobPerformer.InvokePerformFilter(IServerFilter filter, PerformingContext preContext, Func`1 continuation)
ClientConnectionId:cf3220e9-bbf5-40f2-8dc5-0d7836736771
Error Number:-2,State:0,Class:11
Here's the job method which fails:
[AutomaticRetry(Attempts = 0)]
[DisableConcurrentExecution(30 * 60)]
public async System.Threading.Tasks.Task ExecuteAsync(int id, PerformContext context, CancellationToken cancellationToken)
{
...
}
As the timeout of DisableConcurrentExecutionAttribute is already set to 30 minutes, what's the problem here? I even increased the CommandTimeout in the hangfire sql server configuration to 60 seconds:
builder.Services.AddHangfire((provider, config) => config
.SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
.UseSimpleAssemblyNameTypeSerializer()
.UseRecommendedSerializerSettings()
.UseSqlServerStorage(databaseConnectionStr, new SqlServerStorageOptions
{
CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
CommandTimeout = TimeSpan.FromSeconds(60),
SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
QueuePollInterval = TimeSpan.Zero,
UseRecommendedIsolationLevel = true,
DisableGlobalLocks = true,
PrepareSchemaIfNecessary = false
})
.WithJobExpirationTimeout(TimeSpan.FromDays(30 * 6))
.UseFilter(provider.GetRequiredService<SendEMailOnFailureFilter>())
.UseConsole());
If I manually re-queue the same job, it works everytime.
UPDATE:
Here's a screenshot of a failed job where we can see, that it's already failing after just 37 total seconds, which is less than the timeout for DisableConcurrentExecution and the CommandTimeout (SQL) configured in hangfire. On another instance, it failed after just 27 seconds.
UPDATE 2:
As #jaroslav suggested, I tried a dummy job with a 70 second sleep/delay, but that did work flawlessly. Even the DisableConcurrentExecution attribute worked well:
[AutomaticRetry(Attempts = 0)]
[DisableConcurrentExecution(30 * 60)]
public override async Task ExecuteAsync(PerformContext context, CancellationToken cancellationToken)
{
await Task.Delay(70 * 1000, cancellationToken);
}

I suspect that hangfire is doing some other work while executing the task. This exceeds the default sqlCommandTimeout (30 seconds). Try increasing the default SqlCommand timeout:
using (SqlCommand cmd = new SqlCommand(query, con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandTimeout = 3600; // 1 hour
await cmd.ExecuteNonQueryAsync();
}

Related

C# call to MS-SQL stored procedure not receiving parameters [duplicate]

This question already has an answer here:
Error With SqlCommand not accepting Parameter Arguments
(1 answer)
Closed 6 months ago.
The following image is the code used to call MS=SQL stored procedure, as you can see, I am attempting to provide parameters in the request
using (SqlConnection connection = new SqlConnection(sqlAuth)) {
// Open database connectionS
connection.Open();
// Call upon stored procedure
SqlCommand cmd = new SqlCommand("InsertSystem", connection);
cmd.Parameters.Add("#ObjectID", SqlDbType.VarChar).Value = Request.Form["objectid"].ToString();
cmd.Parameters.Add("#SystemID", SqlDbType.VarChar).Value = Request.Form["systemid"].ToString();
cmd.Parameters.Add("#ItemID", SqlDbType.Int).Value = Request.Form["itemid"].ToString();
int records = cmd.ExecuteNonQuery();
// Close database connection
connection.Close();
}
message = "Record Saved<br /><br />";
The error which is returned from this is as follows:
System.Data.SqlClient.SqlException
HResult=0x80131904
Message=Procedure or function 'InsertSystem' expects parameter '#SystemID', which was not supplied.
Source=Core .Net SqlClient Data Provider
StackTrace:
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.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
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)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite, String method)
at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite, String methodName)
at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
at ServiceObjectsWebApp.Pages.ObjectInsertModel.OnPost() in C:\Users\rmcd\Desktop\ServiceObecjts\ServiceObjectsWebApp\Pages\ObjectInsert.cshtml.cs:line 46
at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.ExecutorFactory.VoidHandlerMethod.Execute(Object receiver, Object[] arguments)
at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.<InvokeHandlerMethodAsync>d__29.MoveNext()
This exception was originally thrown at this call stack:
[External Code]
ServiceObjectsWebApp.Pages.ObjectInsertModel.OnPost() in ObjectInsert.cshtml.cs
[External Code]
You're calling a stored procedure so you need to tell it that:
cmd.CommandType = CommandType.StoredProcedure;

Find Reason for The wait operation timed out

I have below code to get data from database. It hosted in WCF Service (IIS Server).
public DataTable GetDocument(int DocumentID)
{
SqlCommand sqlCommand = null;
SqlConnection sqlConnection = null;
SqlDataAdapter sqlDataAdapter = null;
DataTable dataTable = null;
try
{
sqlConnection = new SqlConnection();
sqlConnection.ConnectionString = "Connection_String";
sqlCommand = new SqlCommand();
sqlCommand.CommandText = "dbo.[Get_Document]";
sqlCommand.CommandType = CommandType.StoredProcedure;
sqlCommand.Connection = sqlConnection;
sqlCommand.Parameters.Add(new SqlParameter("#document_id", SqlDbType.BigInt, 8, ParameterDirection.Input, true, 19, 0, "", DataRowVersion.Proposed, DocumentID));
sqlConnection.Open();
sqlDataAdapter = new SqlDataAdapter(sqlCommand);
dataTable = new DataTable("Document");
sqlDataAdapter.Fill(dataTable);
return dataTable;
}
catch (Exception ex)
{
ErrorLog.LogError(ex, "DocumentID = " + DocumentID);
}
finally
{
if (sqlConnection != null)
{
if(sqlConnection.State != ConnectionState.Closed)
sqlConnection.Close();
sqlConnection.Dispose();
sqlConnection = null;
}
if (sqlCommand != null)
{
sqlCommand.Dispose();
sqlCommand = null;
}
if (dataTable != null)
{
dataTable.Dispose();
dataTable = null;
}
if (sqlDataAdapter != null)
{
sqlDataAdapter.Dispose();
sqlDataAdapter = null;
}
}
return null;
}
It is working correctly but some time randomly we got the below timeout exception.
PARAMETER : DocumentID = 987456
EXCEPTION
Error Message: Execution Timeout Expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
Error Source: .Net SqlClient Data Provider
Error Stack Trace: at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
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, Boolean isInternal, Boolean forDescribeParameterEncryption, Boolean shouldCacheForAlwaysEncrypted)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, Boolean inRetry, 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& usedCache, Boolean asyncWrite, Boolean inRetry)
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.Common.DbDataAdapter.FillInternal(DataSet dataset, DataTable[] datatables, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior)
at System.Data.Common.DbDataAdapter.Fill(DataTable[] dataTables, Int32 startRecord, Int32 maxRecords, IDbCommand command, CommandBehavior behavior)
at System.Data.Common.DbDataAdapter.Fill(DataTable dataTable)
at DAL.DocumentController.GetDocument(int DocumentID)
TargetSite : Void OnError(System.Data.SqlClient.SqlException, Boolean, System.Action`1[System.Action])
INNER EXCEPTION
Error Message: The wait operation timed out
BASE EXCEPTION
Error Message: The wait operation timed out
When timeout exception is occurred at that time we logged exception with appropriate stored procedure's parameter. later on when we investigating the exception logs at that time we perform same operation with same parameter but at that time system behaves as expected (not able to replicate exception even with same parameter).
As far as I know many causes involved for timeout exception. We have already set enough timeout so we don't want to increase timeout in our application.
We just want to know the reason of timeout exception why it is occurred in particular time frame (e.g. It is because of any deadlock, connectivity issue etc.) and logged that reason so later on we can investigate in correct direction.
Is there any way to know the reason of timeout exception?
Thanks.
I think you are right. The timeout exception might due to the client request amount overtake the maximum server load or resource deadlock. Whether WCF or SQL server there is a concurrent request limitation. Here is a template to configure this.
<behaviors>
<serviceBehaviors>
<behavior>
<serviceThrottling maxConcurrentCalls="500" maxConcurrentSessions="10000" maxConcurrentInstances="100" />
</behavior>
</serviceBehaviors>
The instancing mode and the concurrency mode have an impact on the way of processing the client's request.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/sessions-instancing-and-concurrency
https://learn.microsoft.com/en-us/dotnet/api/system.servicemodel.servicebehaviorattribute.concurrencymode?view=netframework-4.8
The combination of instancing mode and concurrency mode might cause a deadlock so that results in the timeout exception.
Finally, the database connection string had better a separate username/password, because the process of IIS hosting the WCF application, it will be replaced with the IIS application pool identity.

Cannot create database using Dapper and database name passed in as # variable, why?

I have a code to create database with dapper:
public static bool CreateDatabase(string connectionString, string databaseName)
{
const string DATABASE_CREATE_QUERY = "CREATE DATABASE (#databaseName)";
using (var connection = new SqlConnection(connectionString))
{
var affectedRows = connection.Execute(DATABASE_CREATE_QUERY, new { databaseName });
return affectedRows > 0 ? true : false;
}
}
CreateDatabase("Server=10.10.10.10;User ID=user;Password=password;MultipleActiveResultSets=true;", "TEST_DB");
Every time I run this method, I get an error:
Incorrect syntax near '('.
With trace:
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.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString, Boolean isInternal, Boolean forDescribeParameterEncryption, Boolean shouldCacheForAlwaysEncrypted)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, Boolean inRetry, 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& usedCache, Boolean asyncWrite, Boolean inRetry)
at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry)
at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
at Dapper.SqlMapper.ExecuteCommand(IDbConnection cnn, CommandDefinition& command, Action`2 paramReader) in E:\GitHub\Dapper\Dapper\SqlMapper.cs:line 2827
at Dapper.SqlMapper.ExecuteImpl(IDbConnection cnn, CommandDefinition& command) in E:\GitHub\Dapper\Dapper\SqlMapper.cs:line 570
at Dapper.SqlMapper.Execute(IDbConnection cnn, String sql, Object param, IDbTransaction transaction, Nullable`1 commandTimeout, Nullable`1 commandType) in E:\GitHub\Dapper\Dapper\SqlMapper.cs:line 443
at DbCreator.DbUtils.CreateDatabase(String connectionString, String databaseName) in E:\src_projects\DbCreator\DbUtils.cs:line 48
at DbCreator.***.Run(String connectionString) in E:\src_projects\DbCreator\***.cs:line 23
If I set the query the ugly way
const string DATABASE_CREATE_QUERY = $"CREATE DATABASE {databaseName}";
and run
connection.Execute(DATABASE_CREATE_QUERY);
it all works fine.
If I don't use the brackets () in the QUERY
const string DATABASE_CREATE_QUERY = "CREATE DATABASE #databaseName";
I get an error:
Incorrect syntax near '#databaseName'
I have also tried methods ExecuteScalar, Query, but with the same result.
Any ideas why this wont work the Dapper way?
This is because sp_executesql is being used for parameterizing.This is what is being executed in the database via Dapper interpretation;
exec sp_executesql N'Create Database (#DBName)',N'#DBName nvarchar(4000)',#DBName=N'Test'
See why that wont work with sp_executesql: Table name as variable
Your best bet would be to either create a stored procedure, or use the approach of string replacement.
Because create database statement doesn't require ().
Try :
const string DATABASE_CREATE_QUERY = "CREATE DATABASE #databaseName";

Doing many inserts with entity framework result in => Physical connection is not usable

I use latest entity framework and insert about 425000 entities via a stored procedure.
Then an exception happens. It still did insert 32766 entities.
Code
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);
}
}
}
Error
A transport-level error has occurred when receiving results from the server. (provider: Session Provider, error: 19 - Physical connection is not usable)
How can I fix that error?
UPDATE
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);
}
The exception happens at the return statement!
An unhandled exception of type 'System.Data.Entity.Core.EntityCommandExecutionException' occurred in EntityFramework.SqlServer.dll
Stacktrace:
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)"}
Based on ewahner's suggestion and doing small research about the cause of the error, it is mostly related to a Sql Server limitation (reading the log from the server might give some hints) and one possible solution would be to use a bulk insert. I have used this extension in a project and the results were very good (dozens of times faster then classic EF save of added entities).
If your stored procedure is complex (does some computations, persists some data in other tables etc.) you can still use Bulk insert:
generate an identifier (an insert session identifier)
persist your data via BulkInsert in a session table using the generated identifier as a batch identifier
call the procedure by providing the identifier as an extra parameter
remove data from session table (better via a job which runs outside the operational hours, as deletes have great impact on table usage)

dapper Error converting data type datetime to smalldatetime when executing stored procedure

I have a table in my database with smalldatetime type. And I have a stored procedure that updates data in that table.
The stored procedure gets a #LastLogin smalldatetime parameter with the date to update.
In c# I have a code that calls the stored procedure using dapper:
loginDetails.LastLoginDate = (DateTime)System.Data.SqlTypes.SqlDateTime.MinValue;
db.Execute("stp_UpdateLogin", loginDetails, commandType: CommandType.StoredProcedure);
When I run this I get the following error:
System.Data.SqlClient.SqlException (0x80131904): Error converting data type datetime to smalldatetime.
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.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
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)
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.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite)
at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
at Dapper.SqlMapper.ExecuteCommand(IDbConnection cnn, CommandDefinition& command, Action`2 paramReader) in d:\Dev\dapper-dot-net\Dapper NET40\SqlMapper.cs:line 3310
at Dapper.SqlMapper.ExecuteImpl(IDbConnection cnn, CommandDefinition& command) in d:\Dev\dapper-dot-net\Dapper NET40\SqlMapper.cs:line 1310
at Dapper.SqlMapper.Execute(IDbConnection cnn, String sql, Object param, IDbTransaction transaction, Nullable`1 commandTimeout, Nullable`1 commandType) in d:\Dev\dapper-dot-net\Dapper NET40\SqlMapper.cs:line 1185
at Memoriez.Repositories.UsersRepository.UpdateUser(User user) in f:\Development\Memoriez\Memoriez.Repositories\UsersRepository.cs:line 58
ClientConnectionId:02cae914-507b-4c21-9799-8ec0940fc3d9
How can I make sure that dapper passes what SQL expects?
That's because
(DateTime)System.Data.SqlTypes.SqlDateTime.MinValue = 1/1/1753 12:00:00 AM
While the minimum value for
SMALLDATETIME = 1900-01-01 00:00:00
You could create a helper class:
public static class SqlSmallDateTime
{
public static readonly SqlDateTime MinValue = new SqlDateTime(new DateTime(1900, 01, 01, 00, 00, 00));
}

Categories

Resources