0

I have one List<string> which length is undefined, and for some purpose I'm converting entire List<string> to string, so I want's to check before conversion that it is possible or not(is it gonna throw out of memory exception?) so I can process that much data and continue in another batch.

Sample

int drc = ImportConfiguration.Data.Count;
List<string> queries = new List<string>() { };

//iterate over data row to generate query and execute it
for (int drn = 0; drn < drc; drn++)//drn stands to Data Row Number
{
    queries.Add(Generate(ImportConfiguration.Data[drn], drn));

//SO HERE I WANT"S TO CHECK FOR SIZE
//IF IT"S NOT POSSIBLE IN  NEXT ITERATION THAN I'LL EXECUTE IT RIGHT NOW
//AND EMPTIED LIST AGAIN FOR NEXT BATCH

    if (drn == drc - 1 || drn % 5000 == 0)
    {
        SqlHelper.ExecuteNonQuery(connection, System.Data.CommandType.Text, String.Join(Environment.NewLine, queries));
        queries = new List<string>() { };
    }
}
Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
Nilesh Moradiya
  • 691
  • 1
  • 10
  • 19

3 Answers3

1

You could try:

List<string> theList;

try {
    String allString = String.Join(",", theList.ToArray());
} catch (OutOfMemoryException e) {
    // ... handle OutOfMemoryException exception (e)
}

EDIT

Based on your comment.

You could give an estimation in the following way.

  1. Get available memory: Take a look at this post
  2. Get sum size of your list strings theList.Sum(s => s.Length);

    List<string> theList = new List<string>{ "AAA", "BBB" };
    // number of characters
    var allSize = theList.Sum(s => s.Length);
    
    // available memory
    Process proc = Process.GetCurrentProcess();
    var availableMemory = proc.PrivateMemorySize64;;
    
    if (availableMemory > allSize) {
       // you can try
       try {
          String allString = String.Join(",", theList.ToArray());
       } catch (OutOfMemoryException e) {
          // ... handle OutOfMemoryException exception (e)
       }
    } else {
       // it is not going to work...
    }
    
Community
  • 1
  • 1
DDan
  • 8,068
  • 5
  • 33
  • 52
1

I can't say it is not possible but I think a better way would be to do the join and catch any exceptions:

try
{
     var joined = string.Join(",", list);
}
catch(OutOfMemoryException)
{
     // join failed, take action (log, notify user, etc.)
}

Note: if the exception is happening, then you need to consider a different approach than using a list and joining.

Eren Ersönmez
  • 38,383
  • 7
  • 71
  • 92
  • *I want to check before conversion that it is possible or not* > This is all afterwards... I think it is better to solve the actual issue instead of just failing. – Patrick Hofman Apr 22 '16 at 07:45
  • As string is immutable, i can't afford conversion every time – Nilesh Moradiya Apr 22 '16 at 07:46
  • Acrually i'm batching operations, and i need this check because other 3rd party API is requiring string as input. – Nilesh Moradiya Apr 22 '16 at 07:47
  • 1
    @PatrickHofman catching the exception would be a step towards telling that string join is not the right approach here, if it is happening so often that it is not an "exception". In that case there is something wrong with the design of the whole thing. We can only speculate what that is. – Eren Ersönmez Apr 22 '16 at 07:54
1

Since you are trying to send a large amount of text to a SQL Server instance, you could use SQL Server's streaming support to write the string to the stream as you go, minimizing the amount of memory needed to construct the data to send.

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325