使用EF Core FromSqlInterpolated调用TVF时datetimeoffset列为空如何解决
更新
该问题似乎与同时包含NULL值和有效日期时间的数据集有关。我已修改表值函数(TVF)确保所有日期时间都被CAST(? as datetimeoffset)包裹,但问题仍未解决!
如果我将NULL日期默认设为'0001-01-01T00:00:00.0000000+00:00',则所有功能正常运行。
原始问题
我如何使用Entity Framework的FromSqlInterpolated方法,将SQL的datetimeoffset数据列返回到我的自定义集合中?
我在DbContext上定义了如下自定义IQueryable,其中tvfTaskSourceChecklist是一个表值函数:
public IQueryable<ClientAppTask> TaskSourceChecklist(int companyId, int userId) { return Set<ClientAppTask>().FromSqlInterpolated($"SELECT * FROM dbo.tvfTaskSourceChecklist({companyId},{userId})"); }
ClientAppTask类定义如下:
public class ClientAppTask { public int TaskType { get; set; } public int Id { get; set; } public string Reference { get; set; } public string ContextReference { get; set; } public string ContextTitle { get; set; } public string ContextSubTitle { get; set; } public DateTimeOffset? Scheduled { get; set; } public DateTimeOffset? Deadline { get; set; } }
我在SQL Server Management Studio中执行该表值函数可以正常返回数据,Scheduled和Deadline列有对应值,示例数据如下:
TaskType Id Reference ContextReference ContextTitle ContextSubTitle Scheduled Deadline 1 1 NULL Test Bakery Low Risk Coding Record Check Service NULL NULL 1 1 NULL Test Bakery Low Risk Coding Record Check Service 2021-09-13 14:00:00.0000000 +00:00 2021-09-13 15:00:00.0000000 +00:00 1 1 NULL Test Bakery Low Risk Coding Record Check Service 2021-09-13 20:00:00.0000000 +00:00 2021-09-13 21:00:00.0000000 +00:00
但当我使用如下代码调用Entity Framework Core v3.1.19返回的集合时,所有Deadline和Scheduled的datetimeoffset值都为NULL:
private async Task<List<ClientAppTask>> FetchTaskChecklist(int companyId, int userId) { return await _oltp.TaskSourceChecklist(companyId, userId).ToListAsync(); }
完整TVF脚本如下:
ALTER FUNCTION [dbo].[tvfTaskSourceChecklist] ( @companyId int, @userId int ) RETURNS TABLE AS RETURN ( SELECT 1 AS TaskType, CSE.Id, CS.Reference, E.Reference AS ContextReference, E.Title AS ContextTitle, CS.Title AS ContextSubTitle, CAST(CRIO.UtcTime as datetimeoffset) AS Scheduled, CAST(CASE CSEC.ResponseIntervalMinutes WHEN NULL THEN NULL ELSE DATEADD(mi, CSEC.ResponseIntervalMinutes, CRIO.UtcTime) END as datetimeoffset) AS Deadline FROM tblChecklistServiceEnrolment AS CSE INNER JOIN tblChecklistService AS CS ON CSE.ChecklistServiceId=CS.Id INNER JOIN tblChecklistDefinition AS CD ON CS.ChecklistDefinitionId=CD.Id INNER JOIN tvfEntitiesForChecklist(@companyId, @userId) AS EFU ON CSE.EntityId=EFU.EntityId INNER JOIN tblEntity AS E ON EFU.EntityId=E.Id INNER JOIN tblProxyCompany AS PC ON E.CompanyId=PC.Id INNER JOIN tblChecklistResponseInterval AS CRI ON CS.Id=CRI.ChecklistServiceId LEFT JOIN tblChecklistResponseIntervalOffset AS CRIO ON CRI.Id=CRIO.ResponseIntervalId AND ((E.LocalTimeZoneId IS NOT NULL AND E.LocalTimeZoneId=CRIO.TimeZoneId) OR (PC.DefaultTimeZoneId IS NOT NULL AND PC.DefaultTimeZoneId=CRIO.TimeZoneId OR 47=CRIO.TimeZoneId)) LEFT JOIN tblChecklistServiceEscalation AS ESC ON CS.Id=ESC.ChecklistServiceId AND ESC.EscalationMode=0 AND ESC.Deleted=0 LEFT JOIN tblChecklistServiceEscalationCriteria AS CSEC ON ESC.Id=CSEC.EscalationId AND CSEC.Deleted=0 AND CSEC.CriteriaMode=0 WHERE CD.CompanyId=@companyId AND CS.Deleted=0 AND CS.[Enabled]=1 AND CSE.Deleted=0 AND CSE.[Enabled]=1 AND CRI.Deleted=0 AND CRI.[Status]=0 UNION SELECT 1 AS TaskType, CSE.Id, CS.Reference, E.Reference AS ContextReference, E.Title AS ContextTitle, CS.Title AS ContextSubTitle, CAST(NULL as datetimeoffset) AS Scheduled, CAST(NULL as datetimeoffset) AS Deadline FROM tblChecklistServiceEnrolment AS CSE INNER JOIN tblChecklistService AS CS ON CSE.ChecklistServiceId=CS.Id INNER JOIN tblChecklistDefinition AS CD ON CS.ChecklistDefinitionId=CD.Id INNER JOIN tvfEntitiesForChecklist(@companyId, @userId) AS EFU ON CSE.EntityId=EFU.EntityId INNER JOIN tblEntity AS E ON EFU.EntityId=E.Id WHERE CD.CompanyId=@companyId AND CS.Deleted=0 AND CS.[Enabled]=1 AND CS.AllowAdhoc=1 AND CSE.Deleted=0 AND CSE.[Enabled]=1 );
内容的提问来源于stack exchange,提问作者Andrew HB
相关产品推荐
相关产品推荐

