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

ASP.NET接口返回报表数据最后三字段重复 与数据库查询结果不一致

问题描述

调用自定义Ajax请求对接后端接口时,接口返回数据最后三个字段值重复。已直接在数据库执行对应查询语句校验,确认数据库返回结果和Ajax拿到的接口返回数据存在差异,各环节代码如下。

ASP.NET后端接口代码

[HttpGet]
public List<Reportes> GetScrapReport(string fecha, string fechaend)
{
    try {
        var fechaparametro = new SqlParameter("@fecha", fecha);
        var fechafinparametro = new SqlParameter("@fechafin", fechaend);
        var listareport = _context.Reportes.FromSqlRaw($"SELECT DISTINCT idscrap, fecha, modelo, elemento, nombre, numeroparte, cantidad FROM F_GetScrapReport (@fecha, @fechafin)", fechaparametro, fechafinparametro);
        return listareport.ToList();
    }
    catch 
    {
        return new List<Reportes>();
    }
}

Reportes实体类结构

public class Reportes
{
    [Key]
    public int Idscrap { get; set; }
    public DateTime fecha { get; set; }
    public string modelo { get; set; }
    public string elemento { get; set; }
    public string? nombre { get; set; }
    public string? numeroparte { get; set; }
    public int? cantidad { get; set; }
}

前端Ajax请求函数

function GetScraptime()
{
    var j = 0;
    var fecha = document.getElementById('scraptime');
    var fechafin = document.getElementById('scraptimetwo');
    console.log(fecha.value);
    console.log(fechafin.value);
    if (fecha.value == "" || fechafin.value == "") {
        console.log("Uno de los parametros esta vacio");
    }
    else
    {
        $.ajax({
            method: "GET",
            url: "Reportes/GetScrapReport",
            contentType: "aplication/json; Charset=utf-8",
            data: { 'fecha': fecha.value, 'fechaend': fechafin.value },
            async: true,
            success: function (result)
            {
                console.log(result.length);
                $("#tabletimescrap").html('');
                while (j < result.length) 
                {
                    $("#tabletimescrap").append("<tr>");
                    $("#tabletimescrap").append("<td>" + result[j].idscrap + "</td>");
                    $("#tabletimescrap").append("<td>" + result[j].fecha + "</td>");
                    $("#tabletimescrap").append("<td>" + result[j].modelo + "</td>");
                    $("#tabletimescrap").append("<td>" + result[j].elemento + "</td>");
                    $("#tabletimescrap").append("<td>" + result[j].nombre + "</td>");
                    $("#tabletimescrap").append("<td>" + result[j].numeroparte + "</td>");
                    $("#tabletimescrap").append("<td>" + result[j].cantidad + "</td>");
                    $("#tabletimescrap").append("</tr>");
                    j = j + 1;
                }
                console.log(result);
            }
        });
    }
}

SQL自定义函数实现

CREATE FUNCTION F_GetScrapReport (@fecha varchar(20), @fechafin varchar(20))
RETURNS TABLE
AS RETURN 
(   SELECT [Scrap].IDScrap
              ,[fecha]
              ,M.modelo
              ,[elemento]
              ,P.nombre
              ,P.numeroparte
              ,[cantidad]
          FROM [dbo].[Scrap] FULL OUTER JOIN Scraparte Sc ON dbo.[Scrap].IDScrap = Sc.IDScrap 
          JOIN Modelo M ON dbo.[Scrap].IDModelo = M.IDModelo LEFT JOIN Parte P ON Sc.IDParte = P.IDParte
          WHERE dbo.[Scrap].fecha >= convert(varchar,REPLACE(@fecha,'"','') , 23) AND dbo.[Scrap].fecha<= DATEADD(HOUR,23.9999,convert(varchar, REPLACE(@fechafin,'"',''), 23)))

数据库验证查询语句

SELECT DISTINCT idscrap, fecha, modelo, elemento, nombre, numeroparte, cantidad FROM F_GetScrapReport('2022-07-06','2022-07-06')

数据库查询正确结果截图

异常表现

前端视图渲染结果中,nombre、numeroparte、cantidad三个列的值出现重复,和数据库查询的正确结果完全不符。
前端渲染异常结果截图

问题原因
  1. 核心原因:EF Core实体身份解析机制导致映射错乱
    你给Reportes实体的Idscrap属性标记了[Key]主键特性,但SQL查询因为多表关联,同一个idscrap会对应多行记录(单张报废单可关联多个零件条目)。EF Core做结果映射时,遇到主键值相同的记录会判定为同一个实体,不会新建对象,后续同主键记录的字段值无法被正确映射,直接导致后三个关联字段值重复。
  2. 前端隐患
    循环变量j定义在ajax回调外层,多次快速触发异步请求时会出现计数错乱;另外contentType存在拼写错误(写为aplication,正确为application),GET请求不需要设置该参数,虽不影响当前功能但属于不规范写法。
修复方案

后端修复

二选一即可:

  • 方案1(推荐):新建无主键的DTO类接收查询结果,避免EF主键校验
public class ScrapReportDto
{
    public int Idscrap { get; set; }
    public DateTime fecha { get; set; }
    public string modelo { get; set; }
    public string elemento { get; set; }
    public string? nombre { get; set; }
    public string? numeroparte { get; set; }
    public int? cantidad { get; set; }
}

将接口返回类型改为List<ScrapReportDto>,FromSqlRaw泛型参数同步替换为ScrapReportDto即可。

  • 方案2:保留原有实体,查询时加AsNoTracking()关闭变更跟踪,绕过身份解析
var listareport = _context.Reportes
    .AsNoTracking()
    .FromSqlRaw($"SELECT DISTINCT idscrap, fecha, modelo, elemento, nombre, numeroparte, cantidad FROM F_GetScrapReport (@fecha, @fechafin)", fechaparametro, fechafinparametro);

前端修复

将循环变量移入回调内部,用for循环替代while循环避免计数异常,移除不必要的contentType配置:

success: function (result)
{
    console.log(result.length);
    $("#tabletimescrap").html('');
    for(let j = 0; j < result.length; j++) 
    {
        $("#tabletimescrap").append(`<tr>
            <td>${result[j].idscrap}</td>
            <td>${result[j].fecha}</td>
            <td>${result[j].modelo}</td>
            <td>${result[j].elemento}</td>
            <td>${result[j].nombre}</td>
            <td>${result[j].numeroparte}</td>
            <td>${result[j].cantidad}</td>
        </tr>`);
    }
    console.log(result);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 16:39:38