Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

Xử lý dữ liệu JSON lớn do API Web trả về

Vấn đề của bạn là bạn đang chạy một truy vấn Oracle trả về một số lượng rất lớn kết quả, sau đó tải toàn bộ kết quả đó vào bộ nhớ trước khi tuần tự hóa nó ra HttpResponseMessage .

Để giảm mức sử dụng bộ nhớ, bạn nên tìm và loại bỏ tất cả các trường hợp trong đó toàn bộ tập hợp kết quả từ truy vấn được tải vào một biểu diễn trung gian tạm thời (ví dụ:một DataTable hoặc chuỗi JSON), và thay vào đó, truyền dữ liệu ra ngoài bằng DataReader . Điều này tránh kéo mọi thứ vào bộ nhớ cùng một lúc theo câu trả lời này .

Đầu tiên, từ theo dõi của bạn, có vẻ như bạn có Bật liên kết trình duyệt đã kiểm tra. Vì điều này dường như cố gắng lưu vào bộ nhớ cache toàn bộ phản hồi trong một MemoryStream , bạn sẽ muốn tắt nó như được giải thích trong FilePathResult ném OutOfMemoryException với tệp lớn .

Tiếp theo, bạn có thể phát trực tuyến nội dung của IDataReader trực tiếp sang JSON bằng Json.NET với lớp và trình chuyển đổi sau:

[JsonConverter(typeof(OracleDataTableJsonResponseConverter))]
public sealed class OracleDataTableJsonResponse
{
    public string ConnectionString { get; private set; }
    public string QueryString { get; private set; }
    public OracleParameter[] Parameters { get; private set; }

    public OracleDataTableJsonResponse(string connStr, string strQuery, OracleParameter[] prms)
    {
        this.ConnectionString = connStr;
        this.QueryString = strQuery;
        this.Parameters = prms;
    }
}

class OracleDataTableJsonResponseConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(OracleDataTableJsonResponse);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException("OracleDataTableJsonResponse is only for writing JSON.  To read, deserialize into a DataTable");
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var response = (OracleDataTableJsonResponse)value;

        using (var dbconn = new OracleConnection(response.ConnectionString))
        {
            dbconn.Open();
            using (var selectCommand = new OracleCommand(response.QueryString, dbconn))
            {
                if (response.Parameters != null)
                    selectCommand.Parameters.AddRange(response.Parameters);
                using (var reader = selectCommand.ExecuteReader())
                {
                    writer.WriteDataTable(reader, serializer);
                }
            }
        }
    }
}

public static class JsonExtensions
{
    public static void WriteDataTable(this JsonWriter writer, IDataReader reader, JsonSerializer serializer)
    {
        if (writer == null || reader == null || serializer == null)
            throw new ArgumentNullException();
        writer.WriteStartArray();
        while (reader.Read())
        {
            writer.WriteStartObject();
            for (int i = 0; i < reader.FieldCount; i++)
            {
                writer.WritePropertyName(reader.GetName(i));
                serializer.Serialize(writer, reader[i]);
            }
            writer.WriteEndObject();
        }
        writer.WriteEndArray();
    }
}

Sau đó, sửa đổi mã của bạn để trông giống như sau:

    public HttpResponseMessage Getdetails([FromUri] string[] id)
    {
        var prms = new List<OracleParameter>();
        var connStr = ConfigurationManager.ConnectionStrings["PDataConnection"].ConnectionString;
        var inconditions = id.Distinct().ToArray();
        var strQuery = @"SELECT 
                       STCD_PRIO_CATEGORY_DESCR.DESCR AS CATEGORY, 
                       STCD_PRIO_CATEGORY_DESCR.SESSION_NUM AS SESSION_NUMBER, 
                       Trunc(STCD_PRIO_CATEGORY_DESCR.START_DATE) AS SESSION_START_DATE, 
                       STCD_PRIO_CATEGORY_DESCR.START_DATE AS SESSION_START_TIME , 
                       Trunc(STCD_PRIO_CATEGORY_DESCR.END_DATE) AS SESSION_END_DATE, 
                         FROM 
                         STCD_PRIO_CATEGORY_DESCR, 
                         WHERE 
                        STCD_PRIO_CATEGORY_DESCR.STD_REF IN(";
        var sb = new StringBuilder(strQuery);
        for (int x = 0; x < inconditions.Length; x++)
        {
            sb.Append(":p" + x + ",");
            var p = new OracleParameter(":p" + x, OracleDbType.NVarchar2);
            p.Value = inconditions[x];
            prms.Add(p);
        }
        if (sb.Length > 0)// Should this be inconditions.Length > 0  ?
            sb.Length--;
        strQuery = sb.Append(")").ToString();

        var returnObject = new { data = new OracleDataTableJsonResponse(connStr, strQuery, prms.ToArray()) };
        var response = Request.CreateResponse(HttpStatusCode.OK, returnObject, MediaTypeHeaderValue.Parse("application/json"));
        ContentDispositionHeaderValue contentDisposition = null;
        if (ContentDispositionHeaderValue.TryParse("inline; filename=ProvantisStudyData.json", out contentDisposition))
        {
            response.Content.Headers.ContentDisposition = contentDisposition;
        }
        return response;
    }

Điều này tránh DataSet trong bộ nhớ biểu diễn kết quả.

Tình cờ, tôi nghĩ ra dòng

        if (sb.Length > 0)
            sb.Length--;

thay vào đó phải là:

        if (inconditions.Length > 0)
            sb.Length--;

Tôi tin rằng bạn đang cố gắng loại bỏ dấu phẩy ở cuối trong truy vấn, dấu phẩy này sẽ xuất hiện nếu và chỉ khi inconditions.Length > 0

Xin lưu ý - Tôi không phải là nhà phát triển Oracle và tôi chưa cài đặt Oracle. Để thử nghiệm, tôi đã mô phỏng OracleClient các lớp sử dụng OleDbConnection bên dưới và nó hoạt động tốt.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL Thiếu dấu ngoặc phải theo thứ tự theo câu lệnh

  2. SSL trình điều khiển mỏng Oracle JDBC

  3. Phát hiện lỗi sqlplus trong tập lệnh hàng loạt dos?

  4. Gọi một lệnh gọi hàm trong một chuỗi trong một Thủ tục Oracle

  5. Định cấu hình các điều kiện tiên quyết của gói UTL_MAIL