Azure容器应用中EF Core查询执行超时问题求助
问题:Azure容器应用对接本地SQL Server时EF Core查询超时
在Azure容器应用对接本地SQL Server场景下,EF Core部分查询执行超时,相同代码在本地Docker环境运行正常。仅返回少量列的查询可正常执行,返回约10列及以上时触发超时。
超时查询代码
IQueryable<Disbursement> response = _dataContext.Disbursements .Where(w => w.DisbursementDate <= disbursementDate && !w.DeletedFlag && !w.Paid && w.MethodId == methodId && w.AccountId == accountId) .OrderByDescending(o => o.CreatedOnDateUtc); var result = response.Skip((page - 1) * pageSize) .Take(pageSize) .ToList();
正常查询示例
IQueryable<AccountBillingModel> response = _dataContext.Disbursements.Where(w => w.DisbursementDate <= disbursementDate && !w.DeletedFlag && !w.Paid && w.MethodId == methodId) .Select(s => s.AccountId) .Distinct() .Select(s => new AccountBillingModel { AccountId = s }); return await response.ToListAsync();
Disbursement模型定义
public class Disbursement { public Guid Id { get; set; } public Guid TransactionId { get; set; } public Guid AccountId { get; set; } public Guid MethodId { get; set; } public string ExternalItemId { get; set; } = string.Empty; public string Description { get; set; } = string.Empty; public int Quantity { get; set; } public double PriceExcluding { get; set; } public bool Paid { get; set; } public DateTime DisbursementDate { get; set; } public DateTime? DisbursementRunDate { get; set; } public DateTime? AmendedOnDateUtc { get; set; } public bool DeletedFlag { get; set; } = false; public DateTime CreatedOnDateUtc { get; set; } = DateTime.UtcNow; }
DbContext定义
public class DataContext : DbContext { public DataContext(DbContextOptions options) : base(options) { } public DbSet<Disbursement> Disbursements { get; set; } }
已尝试的排查动作
- 切换EF Core 6/8、.NET Core 6/8版本
- 将异步调用(如
ToListAsync())改为同步ToList()
以上操作均未解决问题
Disbursements表结构
CREATE TABLE [dbo].[Disbursements] ( [Id] UNIQUEIDENTIFIER CONSTRAINT [DF_Disbursements_Id] DEFAULT (newid()) NOT NULL, [AccountId] UNIQUEIDENTIFIER NOT NULL, [MethodId] UNIQUEIDENTIFIER NOT NULL, [ExternalItemId] NVARCHAR(50) NOT NULL, [Description] NVARCHAR(150) NOT NULL, [Quantity] INT NOT NULL, [PriceExcluding] FLOAT (53) NOT NULL, [DisbursementDate] DATETIME NOT NULL, [Paid] BIT CONSTRAINT [DF_Disbursements_Paid] DEFAULT ((0)) NOT NULL, [AmendedOnDateUtc] DATETIME NULL, [CreatedOnDateUtc] DATETIME NOT NULL, [DeletedFlag] BIT CONSTRAINT [DF_Disbursements_DeletedFlag] DEFAULT ((0)) NOT NULL, [DisbursementRunDate] DATETIME NULL, CONSTRAINT [PK_Disbursements] PRIMARY KEY CLUSTERED ([Id] ASC) );
异常堆栈信息
An exception occurred while iterating over the results of a query for context type '****'. Microsoft.Data.SqlClient.SqlException (0x80131904): Execution Timeout Expired. The timeout period elapsed prior to completion of the operation or the server is not responding. ---> System.ComponentModel.Win32Exception (258): Unknown error 258 at Microsoft.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) at Microsoft.Data.SqlClient.TdsParserStateObject.ThrowExceptionAndWarning(Boolean callerHasConnectionLock, Boolean asyncClose) at Microsoft.Data.SqlClient.TdsParserStateObject.ReadSniError(TdsParserStateObject stateObj, UInt32 error) at Microsoft.Data.SqlClient.TdsParserStateObject.ReadSniSyncOverAsync() at Microsoft.Data.SqlClient.TdsParserStateObject.TryReadNetworkPacket() at Microsoft.Data.SqlClient.TdsParserStateObject.TryPrepareBuffer() at Microsoft.Data.SqlClient.TdsParserStateObject.TryReadByte(Byte& value) at Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) at Microsoft.Data.SqlClient.SqlDataReader.TryConsumeMetaData() at Microsoft.Data.SqlClient.SqlDataReader.get_MetaData() at Microsoft.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString, Boolean isInternal, Boolean forDescribeParameterEncryption, Boolean shouldCacheForAlwaysEncrypted) at Microsoft.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean isAsync, Int32 timeout, Task& task, Boolean asyncWrite, Boolean inRetry, SqlDataReader ds, Boolean describeParameterEncryptionRequest) at Microsoft.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry, String method) at Microsoft.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) at Microsoft.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior) at Microsoft.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject) at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.InitializeReader(Enumerator enumerator) at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.<>c.<MoveNext>b__19_0(DbContext _, Enumerator enumerator) at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded) at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext() ClientConnectionId:038757a9-2247-477d-98c5-31eacfa8d39d Error Number:-2,State:0,Class:11", "Exception": "Microsoft.Data.SqlClient.SqlException (0x80131904): Execution Timeout Expired. The timeout period elapsed prior to completion of the operation or the server is not responding. ---> System.ComponentModel.Win32Exception (258): Unknown error 258 at Microsoft.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) at Microsoft.Data.SqlClient.TdsParserStateObject.ThrowExceptionAndWarning(Boolean callerHasConnectionLock, Boolean asyncClose) at Microsoft.Data.SqlClient.TdsParserStateObject.ReadSniError(TdsParserStateObject stateObj, UInt32 error) at Microsoft.Data.SqlClient.TdsParserStateObject.ReadSniSyncOverAsync() at Microsoft.Data.SqlClient.TdsParserStateObject.TryReadNetworkPacket() at Microsoft.Data.SqlClient.TdsParserStateObject.TryPrepareBuffer() at Microsoft.Data.SqlClient.TdsParserStateObject.TryReadByte(Byte& value) at Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) at Microsoft.Data.SqlClient.SqlDataReader.TryConsumeMetaData() at Microsoft.Data.SqlClient.SqlDataReader.get_MetaData() at Microsoft.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString, Boolean isInternal, Boolean forDescribeParameterEncryption, Boolean shouldCacheForAlwaysEncrypted) at Microsoft.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean isAsync, Int32 timeout, Task& task, Boolean asyncWrite, Boolean inRetry, SqlDataReader ds, Boolean describeParameterEncryptionRequest) at Microsoft.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry, String method) at Microsoft.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) at Microsoft.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior) at Microsoft.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject) at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.InitializeReader(Enumerator enumerator) at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.<>c.<MoveNext>b__19_0(DbContext _, Enumerator enumerator) at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded) at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext() ClientConnectionId:038757a9-2247-477d-98c5-31eacfa8d39d Error Number:-2,State:0,Class:11
服务器跟踪结果
- 超时查询仅显示登录,一段时间后登出;正常查询则是登录、执行查询后立即登出。
超时查询生成的SQL示例
SELECT [t0].[id], [t0].[accountid], [t0].[amendedondateutc], [t0].[billrundate], [t0].[billingdate], [t0].[contractid], [t0].[corrolationid], [t0].[createdondateutc], [t0].[creditnotenumber], [t0].[deletedflag], [t0].[description], [t0].[invoicenumber], [t0].[invoicesent], [t0].[methodid], [t0].[ordernumber], [t0].[paid], [t0].[partyid], [t0].[status], [t0].[tenantid], [t0].[tokenid], [t1].[id], [t1].[amendedondateutc], [t1].[createdondateutc], [t1].[deletedflag], [t1].[description], [t1].[externalitemid], [t1].[invoicedescription], [t1].[note], [t1].[priceexcluding], [t1].[quantity], [t1].[transactiondate], [t1].[transactionid] FROM (SELECT TOP(1) [t].[id], [t].[accountid], [t].[amendedondateutc], [t].[billrundate], [t].[billingdate], [t].[contractid], [t].[corrolationid], [t].[createdondateutc], [t].[creditnotenumber], [t].[deletedflag], [t].[description], [t].[invoicenumber], [t].[invoicesent], [t].[methodid], [t].[ordernumber], [t].[paid], [t].[partyid], [t].[status], [t].[tenantid], [t].[tokenid] FROM [dbo].[transactions] AS [t] WHERE [t].[id] = '*****') AS [t0] LEFT JOIN [dbo].[transactionitems] AS [t1] ON [t0].[id] = [t1].[transactionid] ORDER BY [t0].[id]
排查与解决建议
1. 网络层面排查
本地Docker正常但Azure容器应用异常,优先排查跨网络传输问题:
- 测试Azure容器应用到SQL Server的大数据包传输是否正常,可通过
ping -l 1472 <SQL Server IP>验证MTU适配情况 - 在SQL连接字符串中添加
Packet Size=4096,减小单数据包体积,避免传输超时 - 检查本地SQL Server防火墙是否限制了Azure来源的连接,或存在带宽、连接数阈值限制
2. 索引与查询优化
针对超时查询的过滤、排序逻辑创建覆盖索引,减少数据扫描和回表:
CREATE NONCLUSTERED INDEX IX_Disbursements_FilterSort ON dbo.Disbursements ( MethodId, AccountId, DisbursementDate, CreatedOnDateUtc DESC ) INCLUDE ( DeletedFlag, Paid, Id, TransactionId, ExternalItemId, Description, Quantity, PriceExcluding, DisbursementRunDate, AmendedOnDateUtc );
- 执行
SET SHOWPLAN_XML ON;后运行超时查询,确认索引是否被正确调用
3. EF Core查询调整
拆分分页查询逻辑,先获取主键再查询详情,减少单次传输的数据量:
var ids = _dataContext.Disbursements .Where(w => w.DisbursementDate <= disbursementDate && !w.DeletedFlag && !w.Paid && w.MethodId == methodId && w.AccountId == accountId) .OrderByDescending(o => o.CreatedOnDateUtc) .Skip((page - 1) * pageSize) .Take(pageSize) .Select(d => d.Id) .ToList(); var result = _dataContext.Disbursements .Where(d => ids.Contains(d.Id)) .ToList();
4. SQL Server配置检查
- 执行
sp_configure 'remote query timeout', 0; RECONFIGURE;临时关闭远程查询超时限制,验证是否为配置导致 - 查看SQL Server的CPU、内存使用率,排除服务器资源瓶颈
内容的提问来源于stack exchange,提问作者Armand
相关产品推荐
相关产品推荐

