views:

94

answers:

1

Update: False alarm! The source of the error was elsewhere. (See at the end of the question.)

Is it possible that either Linq or foreach can mess up the order of an array?

One of my testers reported to have experienced that the order of a list of items he fed in as input didn't match the order of the final list that was saved in the database. More precisely, the first element became the last.

So I reviewed my code step by step, and I have no clue what should change the order. There is a Linq query and a foreach loop however. Is it possible that one of these can mess up the order of an array?

Code, simplified:

List<FooBar> fooBarList = new List<FooBar>();

string[][] theData = new string[][] { 
    new string[] { "a", "x" },
    new string[] { "b", "y" },
    new string[] { "c", "z" } };

FooBar[] fooBarArray = theData.Select(
    row => new FooBar { Foo = row[0], Bar = row[1] }
    ).ToArray();

foreach (FooBar item in fooBarArray)
{
    int iRank = fooBarList.Count + 1;
    item.Ranking = iRank;
    fooBarList.Add(item);
}

The array of arrays of strings theData is in fact given as an input. It is transformed into an array of business objects. These are then added to a list and assigned a ranking field. This field is written to the database together with "Foo" and "Bar".

After saving the list in the database, the rank of "a" was 3 in that particular case. For me, however, I cannot reproduce the misbehavior...

Update: I was wrong, the data written to the database was correct. The data I looked to was from a business object that was copied from the original one. When copying, the order was mixed up while reading it from the database, and this wrong order was then persisted in the copy of the object... => Accepted Jon's answer saying "LINQ to Objects generally has a predictable ordering - other providers often don't."

+3  A: 

Well, your sample code is only showing LINQ to Objects. How are you inserting the data into the database? If that's using LINQ as well, I strongly suspect that it's the LINQ to SQL (or whatever) side which is causing the issue, not LINQ to Objects.

LINQ to Objects generally has a predictable ordering - other providers often don't.

EDIT: If this happens reproducibly, then you ought to be able to catch it happening in the debugger... that should give you some hints. I suspect that if you try to create a short but complete program which demonstrates the problem, you'll end up finding out what's wrong.

Jon Skeet
I use NHibernate for the O/R mapping. However, the "Ranking" field is a normal integer field: I'm the one who assigns the number. NHibernate simply saves the number in the database. I can see in the database that "a" has the ranking 3, which means the order must already have been changed when the ranking is assigned.
chiccodoro
@chiccodoro: In that case, it shouldn't be happening... you're not using Parallel LINQ as well, are you?
Jon Skeet
Not that I'm aware of (how would I see that? I only have an import System.Linq and the statements listed in the OP), and I couldn't find any potential source of race conditions neither.
chiccodoro
I guess I have to look for the source of the error in another part of the process...
chiccodoro
Uh oh! False alarm! How embarassing! (See update of my question if you're interested...)
chiccodoro