【问题标题】:Entity Framework .NET Core returns 'Data is Null. This method or property cannot be called on Null values.' but not in DebuggerEntity Framework .NET Core 返回“数据为空。不能对 Null 值调用此方法或属性。但不在调试器中
【发布时间】:2019-11-25 16:32:59
【问题描述】:

问题:

在 C#、带有 Angular 6 前端的 IIS 部署解决方案上的 MVC API。

一个在特定列上有 8 个过滤字段的简单 HTML 表通过 API HttpGet 调用在后端运行查询。该函数本身可以正常工作,但对于特定字符串 NOT。例如,在“描述”字段上,后端返回“数据为空”。使用以下字符串时,无法对 Null 值调用此方法或属性。值在前端和后端之间正确传递,API 调用大多返回适当的数据。

但是,app 和比 app 更长的字符串(例如 applicationcert 和更长的字符串(例如 certificate)将返回“Data is Null”错误。

如果我使用f 作为transmittal 的输入,我会收到“数据为空”错误。 但是,如果我在 document 上使用 crc 并且 THEN 使用 f 作为 transmittal 的输入,则函数返回正常数据??

这只发生在部署状态下,调试代码时不会出现问题。调试时,代码会返回预期的结果并始终产生正确的响应。

使用一组“链式” where 语句构建 IQueryable 的服务调用,该 IQueryable 被调用以在序列末尾返回 .ToListAsync()


使用:

  • IIS,版本 10,在虚拟机上运行
  • 操作系统 IIS 虚拟机:Windows Server 2016
  • .Net 核心:2.1
  • EntityFrameworkCore:2.1.11
  • SQL Server 2012(在同一虚拟机上运行)
  • VS 2019
  • SQL Server Management Studio 2018

控制器代码

[HttpGet("[action]")]
public async Task<IActionResult> Search(string TR, string DA, string DO, string RE, string TY, string DD, string DI, string OR, string DE)
        {
        return Ok(await _archiveService.Search(TR, DA, DO, RE, TY, DD, DI, OR, DE));
        }

ArchiveService 代码

public async Task<IEnumerable<object>> Search(
            string transmittal,
            string date,
            string document, 
            string revision,
            string type,
            string description, 
            string discipline, 
            string origin, 
            string destination)
        {
                var result = _db.TblCorrespondenceLog.AsQueryable();

                if (!string.IsNullOrEmpty(transmittal))
                    result = result.Where(f => f.TransmittalNo.Contains(transmittal));

                if (!string.IsNullOrEmpty(date))
                {

                }

                if (!string.IsNullOrEmpty(document))
                    result = result.Where(f => f.CompanyDocumentNo.ToLower().Contains(document));

                if (!string.IsNullOrEmpty(type))
                    result = result.Where(f => f.DocumentType.ToLower() == type);

                if (!string.IsNullOrEmpty(description))
                    result = result.Where(f => f.DocumentDescription.ToLower().Contains(description));

                if (!string.IsNullOrEmpty(discipline))
                    result = result.Where(f => f.Discipline.ToLower() == discipline);

                if (!string.IsNullOrEmpty(origin))
                    result = result.Where(f => f.OriginatorCode.ToLower() == origin);

                if (!string.IsNullOrEmpty(destination))
                    result = result.Where(f => f.SupplierCode.ToLower() == destination);    

                return await result.ToListAsync();
}

给出错误的字段是具有.Contains() 子句的字段

当我使用 SQL 编写器获取发送到服务器的查询时,我得到以下查询,这会在调用 .ToListAsync() 时导致“数据为空”错误:

SELECT [f].[uID], [f].[Action_Required], [f].[Approved_Responded], [f].[Area_Code], [f].[Company_Document_No], 
[f].[Discipline], [f].[Document_Description], [f].[Document_Type], [f].[fileUID], [f].[Link], [f].[Originator_Code], 
[f].[Reference_Document], [f].[ResponsibelEngineer], [f].[ResubDate], [f].[ResubTransmittal], [f].[Rev], 
[f].[Sequential_Number], [f].[Sheet_Number], [f].[Supplier_Code], [f].[TDate], [f].[Transmittal_Date], [f].[Transmittal_No], 
[f].[Transmittal_Type], [f].[TRN_Originator], [f].[TurnAroundDate], [f].[Unit_Code], 
[f].[TransmitUID] 
FROM [tblCorrespondenceLog] AS [f] 
WHERE CHARINDEX(N'f', [f].[Transmittal_No]) > 0

当从 SMSS (SQL Server Management Studio 2018) 触发时,哪个工作得很好?

如果我使用crc 作为document 的输入,我会正常返回数据,但查询只是略有不同:

SELECT [f].[uID], [f].[Action_Required], [f].[Approved_Responded], [f].[Area_Code], [f].[Company_Document_No], 
[f].[Discipline], [f].[Document_Description], [f].[Document_Type], [f].[fileUID], [f].[Link], [f].[Originator_Code], 
[f].[Reference_Document], [f].[ResponsibelEngineer], [f].[ResubDate], [f].[ResubTransmittal], [f].[Rev], 
[f].[Sequential_Number], [f].[Sheet_Number], [f].[Supplier_Code], [f].[TDate], [f].[Transmittal_Date], [f].[Transmittal_No], 
[f].[Transmittal_Type], [f].[TRN_Originator], [f].[TurnAroundDate], [f].[Unit_Code], 
[f].[TransmitUID] 
FROM [tblCorrespondenceLog] AS [f]
WHERE (CHARINDEX(N'f', [f].[Transmittal_No]) > 0) AND (CHARINDEX(N'crc', LOWER([f].[Company_Document_No])) > 0)

所以... 为什么实体框架只在特定字符串和特定组合上给我一个“数据为空”错误。即使对“问题”字段进行过滤(当然使用不同的字符串),该函数也会在哪里返回正确的值?

【问题讨论】:

  • 您通常不想在查询中调用.ToLower(),因为它永远不会在数据库服务器上运行,因此效率非常低。
  • @poke 我已添加该内容以尝试解决此问题。在此之前(即没有 ToLower())查询的响应是否相同?而且,如前所述,对于某些查询字符串,该方法可以正常工作 - 如果可能效率低下 -。它是针对非常特定的字符串而失败的?
  • 您是否尝试过使用 SQL Profiler 来确保对您的数据库执行 sql 查询?此外,对于已部署的网站,请确保数据库用户对 tblCorrespondenceLog 表具有选择权限。
  • 请确保查询返回的数据不为空。并且您正在使用与 iis 相同的数据库?
  • @MohsinMehmood 是的,我已经尝试在同一个生产数据库上的 SMSS 上运行查询。 EntityFramework 生成的 SQL 在数据库上直接调用时会产生正确的结果。但是,相同的数据在 .ToListAsync() 调用上转换为列表时会出错。用户名等都相同,所以这不是问题,因为查询 - 如所示 - 大多返回正确的结果

标签: sql entity-framework asp.net-core-mvc iis-10


【解决方案1】:

是.NET Core实体类与数据库表断开连接造成的;

类配置设置为:

     builder.Property(e => e.DocumentDescription)
            .IsRequired()
            .HasColumnName("Document_Description")
            .HasMaxLength(150);

但数据库表的此字段为allow null,因此有时会返回null,而实体框架不希望看到null

删除.IsRequired() 位就可以了。

     builder.Property(e => e.DocumentDescription)
            //.IsRequired()
            .HasColumnName("Document_Description")
            .HasMaxLength(150);

有趣的是,这并没有在开发环境中产生错误,但在部署时确实会导致问题。我一直无法弄清楚为什么会有差异,但至少现在可以了!

【讨论】:

    猜你喜欢
    • 2012-03-31
    • 1970-01-01
    • 1970-01-01
    • 2022-10-31
    • 1970-01-01
    • 2021-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多