C# 存储过程导致JSON响应最小化MVC中的内存使用

C# 存储过程导致JSON响应最小化MVC中的内存使用,c#,asp.net-mvc,C#,Asp.net Mvc,我目前有一个MVC web应用程序,我正在尝试创建一个类似API的操作结果。此API方法运行一个存储过程,并以JSON格式返回结果作为响应 问题是,在某些情况下,存储过程返回约6.5k行,所有这些数据都进入我的应用程序的内存并将其销毁。这个数据有很多列,都是必需的 所以我的问题是:有没有一种方法可以运行存储过程并将其结果返回给客户端,而不将整个结果集放入服务器上的内存中?也许我可以获取响应sql流并将其提供给响应流 我的当前代码包含内存泄漏,如下所示: public ActionResult G

我目前有一个MVC web应用程序,我正在尝试创建一个类似API的操作结果。此API方法运行一个存储过程,并以JSON格式返回结果作为响应

问题是,在某些情况下,存储过程返回约6.5k行,所有这些数据都进入我的应用程序的内存并将其销毁。这个数据有很多列,都是必需的

所以我的问题是:有没有一种方法可以运行存储过程并将其结果返回给客户端,而不将整个结果集放入服务器上的内存中?也许我可以获取响应sql流并将其提供给响应流

我的当前代码包含内存泄漏,如下所示:

public ActionResult GetOutletsByHierarchyLevel(string SearchTerm, string Level, bool ReturnAll = false)
{
    ...
    var data = db.CollectionFromSql(
        "EXEC [apps].[Rapport_GetOutletsByHierarchyLevel] @SearchTerm,@HierarchyLevel,@ReturnAll",
        new Dictionary<string, object>
            {{"@SearchTerm", SearchTerm}, {"@Level", Level}, {"@ReturnAll", ReturnAll}}
    );


    var jsonResult = Json(new JSONResponse()
    {
        Success = true,
        Data = data.ToList().DynamicSQLToDictionary()
    });

    data = null;

    jsonResult.MaxJsonLength = int.MaxValue;


    return jsonResult;
}

如果还有什么我可以提供给你们的,请告诉我。提前感谢您的推荐/文章

您是否具有对存储过程的代码访问权限?
如果是,则可以在sql级别实现分页:。

我直接从存储过程返回JSON,然后从API方法返回JSON响应需要sql Server 2016或更高版本。我已经编写了助手方法来调用我的存储过程。此函数调用不带参数的存储过程,并以字符串形式返回JSON数组:

public static string GetDataJSONArray(
    string procName,
    string connection = null
)
{
    if (connection == null)
        connection = defaultConnection;

    var sql = procName;
    StringBuilder sb = new StringBuilder();
    using (SqlConnection sqlConnection = new SqlConnection(connection))
    {
        sqlConnection.Open();
        SqlCommand cmd = new SqlCommand(sql, sqlConnection);
        cmd.CommandTimeout = defaultTimeout;
        cmd.CommandType = CommandType.StoredProcedure;

        using (SqlDataReader reader = cmd.ExecuteReader())
        {
            while (reader.Read())
            {
                sb.Append(reader.GetString(0));
            }
        }
    }

    var json = sb.ToString();
    if (string.IsNullOrWhiteSpace(json))
    {
        json = "[]";
    }

    return json;
}
示例程序:

create procedure GetTableRecordCounts
as
begin
    select t.name TableName, i.rows RecordCount
    from sysobjects t, sysindexes i
    where t.xtype = 'U' and i.id = t.id and i.indid in (0,1)
    order by RecordCount desc
    for json path, INCLUDE_NULL_VALUES
end
go
API方法示例:

[HttpGet]
public HttpResponseMessage GetTableRecordCounts()
{
    var jsonString = ProcWrapper.GetDataJSON("GetTableRecordCounts");

    HttpResponseMessage success = Request.CreateResponse(HttpStatusCode.OK);
    success.Content = new StringContent(jsonString, Encoding.UTF8, "application/json");
    return success;
}

除非出于某种原因需要,否则我不会反序列化到API方法中的对象。顺便说一句,我目前使用的方法是将JSON对象或数组作为字符串传递到所有需要输入的进程中,如果进程需要返回结果,我总是将JSON对象或数组作为字符串返回。因此,我的进程只有一个参数,比如@JSON nvarcharmax。我喜欢它的简单性。

您是否考虑过使用JSON直接获取结果,而不是使用各种对象作为中间形式?漏洞在哪里?指控!但是你有证据吗?6.5公里的划船距离没那么远。如果它真的那么大,那么调用它的应用程序可能也会遇到问题或带宽问题。但是您仍然可以访问Response.OutputStream和Response.Flush,您可以一次循环一行,然后逐个提交json。@madreflection hot dang我不知道这是可能的!!!这是SQL Server 2016中新增的一款全新产品。不过要小心:让存储过程返回特定格式的数据会将其与非常特定的用途联系起来。这将您的数据访问与表示层紧密地结合在一起,并且可能会限制其使用,因此您必须为类似的目的编写多个过程。我认为这是一个好主意。例如,youtube API只发送x行,需要另一个请求才能获取下一个x行。我确实可以访问存储过程的代码,但是此API的目标之一是提供所有数据的综合列表-用于创建电子表格,你的客户应该对你的API做一些请求,然后这个客户把这些部分合并到一个地方。