2011-01-06 5 views
6

Ho fatto qualche TDD contro alcune stored procedure esistenti. Restituiscono XML, quindi ho utilizzato LINQ in XML.Come ordinare in .NET. Come un confronto di SQL Server?

Al momento, sto lavorando a un test che dimostrerà che i dati sono stati ordinati correttamente. Il test naviga attraverso l'XML e crea un oggetto IEnumerable di tipo anonimo che contiene le tre colonne che dovrebbero essere ordinate. Da questo, si crea una seconda IEnumerable di classificare la prima:

var sortedColumns = from g in columns 
        orderby g.ColumnA ascending, 
          g.ColumnB ascending, 
          g.ColumnC ascending 
        select g; 

Infine, essa afferma che le colonne ordinate sono gli stessi di quelli non ordinati utilizzando SequenceEquals.

Il problema si presenta quando le regole di confronto del database differiscono dalle regole di confronto correnti. In particolare, .NET posiziona "W-" prima di "Wa" in ColumnB.

C'è un modo per ordinare nello stesso ordine di un confronto SQL Server arbitrario? In caso contrario, come dovrei ordinare nello stesso ordine di SQL_Latin1_General_CP1_CI_AS?

+0

Domande correlate: http://stackoverflow.com/questions/11562042/achieving-consistent-sorting-between-c-sharp-and-sql-using-collationinfo-compare, http://stackoverflow.com/questions/ 9384642/what-net-stringcomparer-is-equivalent-sqls-latin1-general-ci-as, http://stackoverflow.com/questions/5581268/custom-collation-ordering –

risposta

4

Se è un confronto di Windows, quindi si riduce all'impostazione locale e ordinamento appropriati, come in Sort Order Identifiers, che nel mondo .Net passa dalla cultura dell'interfaccia utente attualmente impostata.

Se è un confronto SQL, è un po 'più complicato. Se usi VARCHAR sei fuori di testa. Per NVARCHAR, c'è qualche speranza. Vedere Comparing SQL collations to Windows collations:

regole di un confronto SQL di ordinamento dati non Unicode sono incompatibili con qualsiasi routine di ordinamento che viene fornito dal operativo Microsoft Windows sistema ; tuttavia, l'ordinamento dei dati Unicode è compatibile con una particolare versione delle regole di ordinamento di Windows . Perché il confronto regole per non Unicode e Unicode dati sono diversi, quando si utilizza uno SQL collazione si potrebbe vedere diversi risultati per i confronti degli stessi caratteri, a seconda del tipo di dati sottostante .Ad esempio, se si utilizza il confronto SQL "SQL_Latin1_General_CP1_CI_AS", il non Unicode stringa 'ac' è inferiore la stringa 'ab' perché il trattino ("-") viene ordinato come personaggio separata che viene prima di "b". Tuttavia, se si converte queste stringhe a Unicode e si esegue lo stesso confronto , la stringa Unicode N'a-c ' è considerato essere maggiore di N'ab' perché le regole di ordinamento Unicode usano una "parola ordina "che ignora il trattino.

ai propri scopi (TDD) consiglierei semplicemente stare lontano da personaggi sospetti, come trattino -, o avere due s uno dopo l'altro (questioni SS tedesche), o al capitale I (questioni Colliton turco), sh (Problemi di confronto spagnolo) ecc. Ecc. Attenersi ad un piccolo sottoinsieme di caratteri che riordinano correttamente, come a,A,b,B. Sono serio.

+0

Sfortunatamente, non riusciamo a usare dati puliti - Devo usare quello che c'è. –

+0

Come utilizzare SQLite o SQL CE per l'archivio di test? Hanno collazioni. –

+0

Oppure, "concetto radicale", utilizzare un "database di test unitario" per i test unitari, non lo stesso database che utilizzo per testare l'applicazione con l'ambiente di integrazione. Hmmm. –

0

LINQ-to-SQL non supporta l'utilizzo diretto delle regole di confronto. Se vuoi ottenere uno smistamento speciale, dovrai localizzare i dati, trasformarli in una lista (o qualsiasi altra cosa) e ordinarli tu stesso.

Per ulteriori riferimenti vedere i seguenti due link:

+0

Scusa, suppongo di non essere stato chiaro. Non sto usando LINQ to SQL - sto usando LINQ to XML su qualche XML proveniente da SQL Server. –

+0

Oh, non importa allora. Lascerò solo questa risposta qui, forse aiuta qualcun altro. – MicSim

0

ho sollevato questo da use-own-icomparert-with-linq-orderby.

 MyComparer comparer = new MyComparer(); 
     items = items.OrderByDescending(
        x => property.GetValue(x), comparer).ToList(); 
     break; 

È possibile creare un comparatore personalizzato per le proprie esigenze. (Potrebbe essere necessario un tipo concreto invece di un tipo anonimo per i risultati: non l'ho ancora testato).

+0

Grazie, ma quale comparatore? Esiste un modo generico per creare un confronto che corrisponda a qualsiasi confronto di SQL Server o puoi mostrarmi il codice da confrontare come SQL_Latin1_General_CP_CI_AI? –

+0

Non credo ci sia un IComparer pronto per una raccolta di SQL Server. Dovresti creare una classe che implementa IComparer e fare da sola i confronti appropriati. – Brett

+0

(cont.) Non sto dicendo che sarà carino :) Ovviamente, se si desidera specificamente SQL_Latin1_General_CP1_CI_AI, è possibile eseguire un ToLower() (CI). Immagino una ricerca/sostituzione per gli accenti (AI)? Questo è un po 'più lontano di quello che ho cercato ... – Brett

1

Scrivere un'implementazione personalizzata IComparer che chiama effettivamente al server SQL per confrontare ciascuno dei due valori che viene chiesto di confrontare.

Sarebbe molto lento, un po 'sciocco, ma farebbe esattamente quello che stai chiedendo.

Oppure, se si desidera solo replicare esattamente una sequenza di confronto specifica e non un confronto casuale, scrivere una routine usa e getta da chiamare a SQL Server e creare una raccolta di tutti i caratteri nel server SQL dell'ordine. li inserirà e li utilizzerà per creare un'implementazione personalizzata IComparer che corrisponderà alla sequenza del server SQL senza chiamare il server SQL in fase di esecuzione.

+0

grazie per la risposta. Vorrei poterlo revocare due volte. La segnerei come risposta accettata, tranne per il fatto che la risposta di Remus Rusanu in realtà mi ha impostato sulla strada giusta - quello che ritengo sia il modo giusto per gestire tutti questi problemi - creare i tuoi dati, in un database pulito o farlo in una transazione e tornare indietro alla fine del test. –