You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 21:36:01