Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/29.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 序列化需要作为JSON移植到DataTable的对象列表时遇到OutOfMemoryException_C#_Asp.net_Json_Datatable_Json.net - Fatal编程技术网

C# 序列化需要作为JSON移植到DataTable的对象列表时遇到OutOfMemoryException

C# 序列化需要作为JSON移植到DataTable的对象列表时遇到OutOfMemoryException,c#,asp.net,json,datatable,json.net,C#,Asp.net,Json,Datatable,Json.net,我有一个非常大的对象列表(总共186799个),我正试图将其移植到JSON格式的数据表中。序列化对象列表的总长度为62553299。如何将这些数据以JSON格式从Web服务移植到aspx文件中的DataTable public void GetData() { DataTable dt; string connectionString = "----"; string selectCommand = "SELECT -----"; using (AdomdConn

我有一个非常大的对象列表(总共186799个),我正试图将其移植到JSON格式的数据表中。序列化对象列表的总长度为62553299。如何将这些数据以JSON格式从Web服务移植到aspx文件中的DataTable

public void GetData()
{
    DataTable dt;
    string connectionString = "----";
    string selectCommand = "SELECT -----";
    using (AdomdConnection conn = new AdomdConnection(connectionString))
    {
        conn.Open();
        using (AdomdDataAdapter adapter = new AdomdDataAdapter (selectCommand, conn))
        {
            dt = new DataTable();
            adapter.Fill(dt);
            List<ResourceData> ResourceInfo = new List<ResourceData>();
            ResourceData ResourceInfoRow = null;
            foreach (DataRow dr in dt.Rows)
            {
                ResourceInfoRow = new ResourceData();
                ResourceInfoRow.SourceProject = dr.ItemArray[0].ToString();
                ResourceInfoRow.SourceFile= dr.ItemArray[1].ToString();
                ResourceInfoRow.Project = dr.ItemArray[2].ToString();
                ResourceInfoRow.File = dr.ItemArray[3].ToString();
                ResourceInfoRow.Parent = dr.ItemArray[4].ToString();
                ResourceInfoRow.Id = dr.ItemArray[5].ToString();
                ResourceInfo.Add(ResourceInfoRow);
            }
            JavaScriptSerializer js = new JavaScriptSerializer();
            js.MaxJsonLength = 2147483647;
            Context.Response.Write(js.Serialize(ResourceInfo)); //This is where I hit the OutOfMemoryException
        }
        conn.Close();
    }
}
public void GetData()
{
数据表dt;
字符串连接字符串=“-----”;
string selectCommand=“选择------”;
正在使用(AdomdConnection conn=新AdomdConnection(connectionString))
{
conn.Open();
使用(AdomdDataAdapter=new AdomdDataAdapter(selectCommand,conn))
{
dt=新数据表();
适配器填充(dt);
List ResourceInfo=新列表();
ResourceData ResourceInfoRow=null;
foreach(数据行dr在dt.行中)
{
ResourceInfoRow=新的ResourceData();
ResourceInfoRow.SourceProject=dr.ItemArray[0].ToString();
ResourceInfoRow.SourceFile=dr.ItemArray[1].ToString();
ResourceInfoRow.Project=dr.ItemArray[2].ToString();
ResourceInfoRow.File=dr.ItemArray[3].ToString();
ResourceInfoRow.Parent=dr.ItemArray[4].ToString();
ResourceInfoRow.Id=dr.ItemArray[5].ToString();
resourceinfow.Add(resourceinfow);
}
JavaScriptSerializer js=新的JavaScriptSerializer();
js.MaxJsonLength=2147483647;
Context.Response.Write(js.Serialize(ResourceInfo));//这就是我遇到OutOfMemoryException的地方
}
康涅狄格州关闭();
}
}
因为我使用的是DataTable插件,所以我必须以json格式将数据移植回


感谢您的回复。

很可能您的字符串对于内存来说太大了,或者字符串本身太大了(2gb)。您尝试序列化许多对象。因此,最好的方法可能是将对象拆分为多个卡盘以进行序列化。或者您可以尝试其他转换器,如:。Newtonsoft序列化程序是一个快速且可能是最常用的序列化程序。Newtonsoft序列化程序还可以使用流转换为json:。可以直接写入响应对象。

显然,您试图序列化为非常大的字符串,然后将该字符串写入
上下文.Response
流时内存不足。一种解决方案是使用和执行以下操作,即直接从数据库流式传输,而无需将查询的全部内容加载到内存中。虽然我还没有尝试过,但这可能对一个新的应用程序有效

但是,您使用的是,它没有直接序列化到流的方法。尽管如此,由于序列化的是一个
IEnumerable
,因此应该可以分别序列化每个项目,然后分别编写每个项目,并根据以下要求手动将整个项目括在括号中:

公共静态类JavaScriptSerialized
{
公共静态void SerializeToStream(此JavaScriptSerializer序列化程序、IEnumerable集合、流)
{
if(序列化程序==null | |集合==null | |流==null)
抛出新ArgumentNullException();
var writer=newstreamwriter(stream,newutf8encoding(false));//不要处理!
作者:写(“[”);
长计数=0;
var sb=新的StringBuilder();
var buffer=新字符[4000];
foreach(集合中的var项)
{
如果(计数>0)
作者:写(“,”);
sb.长度=0;
序列化器。序列化(项,sb);
写(某人,缓冲区);
计数++;
}
作者:写(“]”);
writer.Flush();
}
}
公共静态类TextWriterExtensions
{
公共静态无效写入(此TextWriter写入程序,StringBuilder sb,char[]buffer=null)
{
if(sb==null | | writer==null)
抛出新ArgumentNullException();

简而言之,JavascriptSerializer中的if(buffer!=null&&buffer.Length有多个重载。如果使用返回字符串的重载,则StringBuilder的最大.ToString()容量将被限制为刚好超过100.000.000个字符(在.net中字符串长度限制)

因此,在提供StringBuilder的地方使用重载。然后在序列化之后,每次获取字符串块,其中.ToString(索引,长度)不超过最大大小100.000.000个字符左右

    public void Serialize(object obj, StringBuilder output)
    {
        Serialize(obj, output, SerializationFormat.JSON);
    }

    //usage afterwards
    sb.ToString(0, 100000);

请参见

假设您有StartOffset和Length参数,并且只向用户返回有限的结果集,就像许多公共API(facebook、instagram、twitter等)一样这不是很好吗?显而易见的事情是流到<代码>上下文.Real.OutPuthStudio,但是显然没有方法写入流,这样就不存在了。你可以考虑切换到直接流行。谢谢彼得。正如您建议的Peter,我拆分了数据。在我的aspx页面中,我使用$.when(x,y).done(函数(a,b){}来获得两个json数据集,然后使用$.merge来合并数据。
        var stream = Context.Response.OutputStream;

        var query = from dr in dt.Rows.Cast<DataRow>()
                    select new
                    {
                        SourceProject = dr.ItemArray[0].ToString(),
                        SourceFile = dr.ItemArray[1].ToString(),
                        Project = dr.ItemArray[2].ToString(),
                        File = dr.ItemArray[3].ToString(),
                        Parent = dr.ItemArray[4].ToString(),
                        Id = dr.ItemArray[5].ToString(),
                    };

        var js = new JavaScriptSerializer();
        js.MaxJsonLength = 2147483647;

        js.SerializeToStream(query, stream);
    //.Net source
    internal string Serialize(object obj, SerializationFormat serializationFormat)
    {
        StringBuilder sb = new StringBuilder();
        Serialize(obj, sb, serializationFormat);
        return sb.ToString();
    }
    public void Serialize(object obj, StringBuilder output)
    {
        Serialize(obj, output, SerializationFormat.JSON);
    }

    //usage afterwards
    sb.ToString(0, 100000);