Orderby () non ordina correttamente i numeri c #

Sto scrivendo un’app per la mia azienda e sto attualmente lavorando sulla funzionalità di ricerca. Quando un utente cerca un object, voglio visualizzare la versione più alta (che è memorizzata in un database).

Il problema è che la versione è archiviata come stringa invece di int e quando eseguo un OrderBy (q => q.Version) sui risultati, vengono restituiti come

1 10 11 2 3 ... 

Ovviamente 2 arriva prima delle 10.

C’è un modo per me di trasmettere la versione come un intero o c’è un semplice IComparer là fuori? Non ho trovato nulla di sostanziale finora.

Ho provato a fare questo:

 var items = (from r in results select r).OrderBy(q => Int32.Parse(q.Version)); 

Questo compila ma non funziona.

Int32.Parse non è supportato dal traduttore LinqToSql. Convert.ToInt32 è supportato.

http://msdn.microsoft.com/en-us/library/sf1aw27b.aspx

http://msdn.microsoft.com/en-us/library/bb882655.aspx

Il tuo problema è da qualche altra parte, i seguenti lavori:

 new[] { "1", "10", "2", "3", "11" } .OrderBy(i => int.Parse(i)) .ToList() .ForEach(Console.WriteLine); 

Se il tuo problema è LINQ to SQL, allora ciò che sta accadendo è che CLR sta cercando di creare SQL dal tuo LINQ e non capisce int.Parse . Quello che puoi fare è innanzitutto ottenere i dati da SQL e ordinarli una volta caricati tutti i dati:

 var items = (from r in results select r) .ToList() .OrderBy(q => Int32.Parse(q.Version)); 

Dovrebbe farlo

Se non sei in grado di modificare la definizione della tabella (quindi la versione è di tipo numerico) e la tua query è realmente elencata (se non usi skip, o prendi o riduci il numero di risultati), il meglio che puoi fare è chiamata “ToList” sui risultati non ordinati, che quando si applica un lambda OrderBY ad esso avverrà nel codice, piuttosto che provare a farlo al termine di SQL Server (e che ora dovrebbe funzionare).

Perché stai selezionando in un lambda? Perché non basta ordinare nella query?

 var query = from r in items orderby int.Parse( r ) select r; 

Ora che sappiamo che stai usando LINQ to SQL, potresti prendere in considerazione l’idea di effettuare una chiamata SQL standard su questo facendo qualcosa come:

 Select ..., Cast( TextWhichShouldBeIntCol As int ) As IntCol From ... 

O anche

 Select ..., Cast( TextWhichShouldBeIntCol As int ) As IntCol From ... Order By Cast( TextWhichShouldBeIntCol As int ) 

Questo si riverserà nel LINQ come un int (e se si utilizza la seconda iterazione, essere ordinato). Questo evita di dover passare attraverso il set di risultati due volte in LINQ (una volta per l’interrogazione, una volta per l’ordine).

C’è un pezzo di codice fantastico che fa un ottimo lavoro quando si tratta di ordinamento naturale. Il suo nome è AlphanumComparator .

Codice di esempio:

 var ordered = Database.Cars.ToList().OrderBy(c => c.ModelString, new AlphanumComparator()); 

Si noti che l’elenco deve essere in memoria.

Se ottieni la versione C #, fai questo:

 AlphanumComparator : IComparer 

e

 public int Compare(string x, string y) 

Ho fatto un test. Ho il codice seguente.

 string[] versions = { "1", "2", "10", "12", "22", "30" }; foreach (var ver in versions.OrderBy(v => v)) { Console.WriteLine(ver); } 

Come previsto, il risultato è 1, 10, 12, 2, 22, 30 Quindi, consente di modificare versions.OrderBy(v => v)) in versions.OrderBy(v => int.Parse(v))) . E funziona bene: 1, 2, 10, 12, 22, 30

Penso che il tuo problema sia che hai caratteri non ben definiti nella tua stringa come ‘.’. Che tipo di eccezione ottieni?

prova questo:

 var items = results.(Select(v => v).OrderBy(v => v.PadLeft(4)); 

funzionerà in Linq2Sql

Perché stai ordinando se hai solo bisogno della “versione più alta”? Sembra che potresti evitare un po ‘di overhead se hai usato Max ().

Inoltre, dovresti davvero cambiare il tipo di colonna in intero.

 var items = (from r in results select r).OrderBy(q => Convert.ToInt32(q.Version)); 

Certamente …

Sembra che tu abbia un valore di testo anziché un valore numerico.

Se hai bisogno di ordinare, puoi provare:

 var items = (from r in results select r); return items.OrderBy( v=> Int.Parse(v.Version) ); 
 var query = from r in items let n = int.Parse(r) orderby n select n; 
 var items = (from v in results select v).ToList().OrderBy(x => int.Parse(x.Version));