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

EF Core 6过滤查询出现「Data is Null」错误的排查求助

问题原因

你的实体类tblAttendance中,LogoutDate和LogoutTime被定义为非可空值类型(DateTime、TimeSpan),但数据库中存在LogoutTime为NULL的记录(比如样本数据里ID为724075的行)。

  • 全量查询时你通过Select映射到AttendanceData,推测AttendanceData中对应的字段是可空类型,因此能正常处理NULL值;
  • 当直接查询实体tblAttendance(不管是LINQ过滤还是FromSqlRaw)时,EF Core无法将数据库的NULL值赋值给非可空的实体属性,从而抛出「Data is Null」错误。
解决方案

1. 修正实体类的可空性(最根本的解决方式)

将数据库中允许为NULL的字段,在实体类中改为可空值类型:

public partial class tblAttendance
{
    public long id { get; set; }
    public string? UserName { get; set; }
    public DateTime LoginDate { get; set; }
    public TimeSpan LoginTime { get; set; }
    public DateTime? LogoutDate { get; set; } // 改为可空
    public TimeSpan? LogoutTime { get; set; } // 改为可空
    public string? ComputerName { get; set; }
    public string? LogonServer { get; set; }
}

2. 在查询中处理NULL值(不修改实体类的情况下)

如果暂时不想修改实体类,可以在SQL查询中给NULL字段设置默认值,避免EF Core转换失败:

SELECT 
    id,
    UserName,
    LoginDate,
    LoginTime,
    ISNULL(LogoutDate, '1900-01-01') AS LogoutDate,
    ISNULL(LogoutTime, '00:00:00') AS LogoutTime,
    ComputerName,
    LogonServer
FROM tblAttendance 
WHERE DATEPART(year, loginDate) = 2023 AND DATEPART(month, loginDate) = 6

3. 使用EF Core LINQ查询替代拼接SQL(更安全,避免注入)

推荐用LINQ构建查询,既安全又能统一处理NULL值:

var query = dbContext.tblAttendances.AsQueryable();

// 添加过滤条件
if (!string.IsNullOrEmpty(userName))
{
    query = query.Where(a => a.UserName == userName);
}

if (!string.IsNullOrEmpty(computerName))
{
    query = query.Where(a => a.ComputerName == computerName);
}

if (loginDate.Ticks > 0)
{
    query = query.Where(a => a.LoginDate.Year == loginDate.Year && a.LoginDate.Month == loginDate.Month);
}

// 映射到AttendanceData并处理NULL
var results = query.Select(a => new AttendanceData
{
    UserName = a.UserName ?? "",
    LoginDate = a.LoginDate,
    LoginTime = a.LoginTime,
    LogoutDate = a.LogoutDate ?? DateTime.MinValue, // 可根据业务需求调整默认值
    LogoutTime = a.LogoutTime ?? TimeSpan.Zero,
    ComputerName = a.ComputerName ?? "",
    LogonServer = a.LogonServer ?? ""
}).ToList();

4. 修复SQL拼接的安全问题(如果坚持用FromSqlRaw)

你的原始SQL拼接存在SQL注入风险,必须改用参数化查询:

var baseQuery = @"SELECT * FROM tblAttendance WHERE 1=1 ";
var parameters = new List<SqlParameter>();

if (!string.IsNullOrEmpty(userName))
{
    baseQuery += "AND UserName = @userName ";
    parameters.Add(new SqlParameter("@userName", userName));
}

if (!string.IsNullOrEmpty(computerName))
{
    baseQuery += "AND ComputerName = @computerName ";
    parameters.Add(new SqlParameter("@computerName", computerName));
}

if (loginDate.Ticks > 0)
{
    baseQuery += "AND DATEPART(year, LoginDate) = @year AND DATEPART(month, LoginDate) = @month ";
    parameters.Add(new SqlParameter("@year", loginDate.Year));
    parameters.Add(new SqlParameter("@month", loginDate.Month));
}

var results = dbContext.tblAttendances.FromSqlRaw(baseQuery, parameters.ToArray()).ToList();

内容的提问来源于stack exchange,提问作者Geoff

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 11:50:04