sharpiepen
sharpiepen

Reputation: 71

alternative to a foreach loop and a string builder

I have a function that gets a collection of entities, and then appends quotes and commas to the string to update the collection in the DB. This is taking an insane amount of time, it's very inefficient, but I can't think of an alternative:

IEntityCollection c = Transactions.EvalToEntityCollection<ITransactions>(Store, key, item);

int max = transes.Count <= 750 ? transes.Count : 750;  // DB times out if there are more than 750, so 750 is the limit
int i = 0;
int t = transes.Count;
StringBuilder sb = new StringBuilder();

foreach (ITransactions trans in transes)
{
    sb.Append("'");
    sb.Append(trans.GUID);
    sb.Append("',");
    i++;
    t--;

    if (i == max || t == 0)
    {
        sb.Remove(sb.Length - 1, 1);

        //in here, code updates a bunch of transactions (if <=750 transaction)

        i = 0;
        sb = new StringBuilder();
    }
}

Upvotes: 7

Views: 2461

Answers (3)

Marc Wittmann
Marc Wittmann

Reputation: 2361

String builder is efficient. Doing it 750 times (which is your max) will definetly NOT take a measurable amount longer than any othe technique available.

Please comment out the StringBuilder part and run the project

sb.Append("'");
sb.Append("',");

I bet it will take exactly the same time to complete.

Upvotes: 0

Lasse V. Karlsen
Lasse V. Karlsen

Reputation: 391466

Seems you want to do this:

  1. Group the transaction numbers into batches of maximum 750 entities
  2. Put all those transaction numbers in one group into one string delimited by comma and surrounded by single quotes

If so then here's the code to build the batches:

const int batchSize = 750;
List<List<Transaction>> batches =
    transes
    .Select((transaction, index) => new { transaction, index })
    .GroupBy(indexedTransaction => indexedTransaction.index / batchSize)
    .Select(group => group.Select(indexedTransaction => indexedTransaction.transaction).ToList())
    .ToList();
foreach (var batch in batches)
{
    // batch here is List<Transaction>, not just the GUIDs
    var guids = string.Join(", ", batch.Select(transaction => "'" + transaction.GUID + "'"));
    // process transaction or guids here
}

Upvotes: 1

Matt Burland
Matt Burland

Reputation: 45155

Something like this perhaps?

var str = String.Join(",", transes.Select(t => string.Format("'{0}'", t.GUID)))

But since you have the comment in your code that it times out with > 750 records, your "insane amount of time" might be from the database, not your code.

String.Join is a really handy method when you want to concatenate a list of stuff together because it automatically handles the ends for you (so you don't end up with leading or trailing delimiters).

Upvotes: 3

Related Questions