I’m using this code to update some records of a table which has around 600k records:
var someRecords = myContext.Commits.Where(c => c.ProjectName == "BSA" && c.RepoName == "sales-SalesApplication-Command" && c.CommitterUniqueName == null);
foreach (var commit in someRecords)
{
commit.CommitterUniqueName = GetUniqueName(commit.CommitterName, myContext);
}
myContext.SaveChanges();
When the linq returns 346 rows I strangely get a timeout error after 30 secs. This is strange because the same update using SQL Mgmt studion runs in no time:
update Devex_Commit
set CommitterUniqueName = 'abc'
where ProjectName = 'BSA'
and RepoName = 'sales-SalesApplication-Command'
and CommitterUniqueName is null
When I look at the debug logs of EF, I see that it uses the Id field to update the records:
fail: 16.05.2024 14:17:56.737 RelationalEventId.CommandError[20102] (Microsoft.EntityFrameworkCore.Database.Command)
Failed executing DbCommand (30,026ms) [Parameters=[@p1='?' (DbType = Int32), @p0='?' (Size = 4000)], CommandType='Text', CommandTimeout='30']
SET IMPLICIT_TRANSACTIONS OFF;
SET NOCOUNT ON;
UPDATE [Devex_Commit] SET [CommitterUniqueName] = @p0
OUTPUT 1
WHERE [Id] = @p1;
fail: 16.05.2024 14:17:56.794 CoreEventId.SaveChangesFailed[10000] (Microsoft.EntityFrameworkCore.Update)
An exception occurred in the database while saving changes for context type 'DevExDataJob.Models.DevexContext'.
Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while saving the entity changes. See the inner exception for details.
---> Microsoft.Data.SqlClient.SqlException (0x80131904): Execution Timeout Expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
When I slightly change the linq to return just one row, all works fine:
var someRecords = myContext.Commits.Where(c => c.ProjectName == "BSA" && c.RepoName == "sales-SalesApplication-Command" && c.CommitterUniqueName == null && c.Id == 123);
foreach (var commit in someRecords)
{
commit.CommitterUniqueName = GetUniqueName(commit.CommitterName, myContext);
}
myContext.SaveChanges();
The debug log of EF in this case has no change:
info: 16.05.2024 13:48:42.897 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
Executed DbCommand (18ms ) [Parameters=[@p1='?' (DbType = Int32), @p0='?' (Size = 4000)], CommandType='Text', CommandTimeout='30']
SET IMPLICIT_TRANSACTIONS OFF;
SET NOCOUNT ON;
UPDATE [Devex_Commit] SET [CommitterUniqueName] = @p0
OUTPUT 1
WHERE [Id] = @p1;
When I debug my original code which returns 365 rows, and bring the execution out of the foreach loop after only one record is updated, I still get the same timeout! I’m totally confused..
I don’t want to increase the timeout threshold of EF as the same update query runs in no time.
Please advise.