【发布时间】:2021-12-13 19:48:39
【问题描述】:
我有一个间歇性问题,我似乎无法深入了解 .NET Framework 4.6 MVC API (C#) 使用需要很长时间的 Entity Framework 6(运行时 v4.0.30319)存储过程调用回应。
存储过程托管在 Azure SQL DB 上。
这是一个不起眼的过程,它会询问几张表格,为营养师提供他们客户的最新数据和网站互动。
ALTER PROCEDURE [PORTAL].[GetNutritionistCustomers]
@id_usernut varchar(20)
AS
WITH Activity AS (
SELECT LastActivity = MAX(ExecutionDate),
ded.UserName
FROM portal.DailyExecutionData ded
WHERE ded.ExecutionDate < GETDATE()
GROUP BY ded.UserName
),
Logging AS (
SELECT LastLogin = MAX(l.LoggedOnDate),
l.UserName
FROM PORTAL.Logins l
WHERE l.LoginType = 'Direct Client'
GROUP BY l.UserName
)
SELECT unc.CompanyCode,
a.ACCOUNT,
ad.ADDRESS1,
un.ID_UserNut,
ueu.ExpirationDate,
Expired = CAST(CASE WHEN ueu.ExpirationDate < GETDATE() THEN 1 ELSE 0 END AS BIT),
LastActive = la.LastActivity,
l.LastLogin
FROM UK_Nutritionist un
JOIN UK_NutCompany unc ON un.ID_UserNut = unc.ID_UserNut
JOIN UK_EnabledUsers ueu ON unc.CompanyCode = ueu.UserName
JOIN Klogix.ACCOUNT a ON ueu.ID_User = a.ACCOUNTID
LEFT JOIN Klogix.ADDRESS ad ON a.ADDRESSID = ad.ADDRESSID AND ad.IsPrimary = 1
LEFT JOIN Activity la ON ueu.UserName = la.UserName
LEFT JOIN Logging l ON ueu.UserName = l.UserName
WHERE un.ID_UserNut = @id_usernut
在 SSMS 或 ADS 中运行此过程平均需要大约 50-100 毫秒才能完成。这是一致的,表的索引很好,查询计划是所有的索引搜索。没有 Key 或 RID 查找危险信号。
在使用探查器进行调查后,我确定发生的情况是 EF 创建了一个连接,调用了该过程。我可以看到 RPC 进入了,EF 达到了连接超时时间,然后我们得到 RPC 完成,数据返回给 EF,代码旋转出一个 pocs 列表以 json 形式返回给调用者。
[HttpGet]
[Route("Customers")]
public HttpResponseMessage Get()
{
try
{
if (IsTokenInvalid(Request))
return Request.CreateResponse(HttpStatusCode.Unauthorized);
var nutritionistCustomers = new ExcdbEntities().GetNutritionistCustomers(TokenPayload.Nutritionist).Select(x => new NutritionistCustomers()
{
Account = x.ACCOUNT,
Address = x.ADDRESS1,
CompanyCode = x.CompanyCode,
ExpirationDate = x.ExpirationDate,
expired = x.Expired,
LastActive = x.LastActive,
LastLogin = x.LastLogin
}).ToList();
return Request.CreateResponse(HttpStatusCode.OK, GenerateResponse(nutritionistCustomers))
}
catch (Exception e)
{
return Request.CreateResponse(HttpStatusCode.InternalServerError, GenerateResponse(e));
}
}
如果我更改了连接的超时时间,那么 SQL 在释放数据之前等待的时间会更改。
我认为这可能与托管 API 的 Azure 应用服务有关,但事实证明,在 Visual Studio 的调试中运行它也有同样的问题。
短期修复是重新编译存储过程。这将立即返回数据。但在未来某个不确定的时间点,同样的程序会突然再次表现出这种行为。
只有这个过程才能做到这一点,所有其他 EF 交互,无论是 linq 到 sql 表还是视图询问,以及所有其他过程似乎都表现良好。 这种情况以前在具有相同架构的旧系统中发生过,尽管它是不同数据库上的不同过程。
虽然缩短超时是一种解决方法,但它是一个系统范围的值,即使是 10 秒,足以应对系统故障,对于这个应该是即时的客户选择屏幕来说也太长了。 另外,如果有人知道可能发生了什么,我宁愿解决根本问题。
我已经考虑过在语句中使用 OPTION_RECOMPILE,但这样做感觉不对。
如果其他人经历过这种情况并有任何见解,我将不胜感激,因为它让我分心。
【问题讨论】:
-
我在 SSMS 调用中添加了从分析器中删除的 EF 上下文设置。我认为重要的是:
set transaction isolation level read committed当它出现问题时,我会在 SSMS 中收到未提交的事务警告,我认为这就是等待锁解决的问题。我不确定是什么原因造成的,也许是 ADF 管道的问题? Anyhoo,我已在 proc 本身的编译上下文中将事务隔离级别读取设置为未提交。哈基,但它的伎俩。现在我需要调查真正的原因。
标签: c# sql-server azure entity-framework stored-procedures