2011-01-06 5 views
6

Zrobiłem niektóre TDD przeciwko niektórych istniejących procedur przechowywanych. Zwracają XML, więc używam LINQ do XML.Jak sortować w .NET Tak jak w przypadku sortowania SQL Server?

W tej chwili pracuję nad testem, który udowodni, że dane zostały odpowiednio posortowane. Test przechodzi przez XML i tworzy IEnumerable anonimowego typu zawierającego trzy kolumny, które powinny być posortowane. Z tym, że tworzy drugi IEnumerable sortując pierwszy:

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

Wreszcie stwierdza, że ​​posortowanych colums są takie same jak te z użyciem SequenceEquals nieposortowane.

Problem występuje, gdy sortowanie w bazie danych różni się od bieżącego sortowania. W szczególności .NET umieszcza "W-" przed "Wa" w kolumnie B.

Czy istnieje sposób sortowania w tej samej kolejności, co arbitralne sortowanie programu SQL Server? Jeśli nie, to w jaki sposób mogę sortować w tej samej kolejności, co SQL_Latin1_General_CP1_CI_AS?

+0

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

Odpowiedz

4

Jeśli jest to sortowanie w systemie Windows, to sprowadza się do ustawienia odpowiedniej lokalizacji i porządku sortowania, jak w Sort Order Identifiers, która w świecie .NET idzie według aktualnie ustawionej kultury interfejsu użytkownika.

Jeśli jest to sortowanie SQL, to jest nieco bardziej skomplikowane. Jeśli używasz VARCHAR, jesteś poza blokadą. W przypadku NVARCHAR istnieje pewna nadzieja. Zobacz Comparing SQL collations to Windows collations:

zasady SQL zestawień dla sortowania danych non-Unicode są niezgodne z każdy rutynowych sortowania, który jest dostarczany przez operacyjnym Microsoft Windows systemu ; jednak sortowanie danych Unicode jest zgodne z konkretną wersją reguł sortowania systemu Windows . Ponieważ porównania zasady non-Unicode i Unicode danych są różne, w przypadku korzystania z SQL sortowania można zobaczyć różne wyniki dla porównania tych samych znaków, w zależności od bazowego typu danych.Na przykład, jeśli używasz sortowanie SQL „SQL_Latin1_General_CP1_CI_AS”, tym non-Unicode string „ac” jest mniejsza niż ciąg „ab”, ponieważ łącznik („-”) są klasyfikowane jako odrębny charakterem przed "b". Jeśli jednak przekonwertować te ciągi Unicode i wykonać taką samą porównania , ciąg Unicode n'a-c „ jest uważany za większy niż N'ab” ponieważ reguły sortowania Unicode używać „Wyraz sortuj ", który ignoruje łącznik.

Dla swoich celów (TDD) Polecam po prostu pobyt z dala od podejrzanych znaków, jak myślnik - lub posiadające dwa s jedna po drugiej (kwestie niemiecki SS) lub kapitału I (problemy turecki colliton) sh (Hiszpańskie problemy z sortowaniem) itp. ... Trzymaj się małego podzbioru znaków, które odpowiednio sortują, np. a,A,b,B. Jestem poważny.

+0

Niestety, nie używamy czystych danych - muszę użyć tego, co tam jest. –

+0

Co z używaniem SQLite lub SQL CE dla magazynu testowego? Oni mają zbiory. –

+0

Lub "radykalna koncepcja", użyj "jednostkowej bazy testowej" dla testów jednostkowych, a nie tej samej bazy danych, której używam do testowania aplikacji w środowisku integracyjnym. Hmmm. –

0

LINQ-to-SQL nie obsługuje bezpośredniego użycia sortowania. Jeśli chcesz uzyskać specjalne sortowanie, musisz pobrać dane lokalnie, przekształcić je na listę (lub cokolwiek innego) i posortować samemu.

Dla dalszego odniesienia patrz poniższe dwa linki:

+0

Przepraszam, domyślam się, że nie było jasne. Nie używam LINQ do SQL - używam LINQ do XML na niektórych XML pochodzących z SQL Server. –

+0

Och, nieważne. Pozwolę ci odpowiedzieć tutaj, może to pomoże komuś innemu. – MicSim

0

mam podniósł ten z use-own-icomparert-with-linq-orderby.

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

Można utworzyć niestandardowego porównywalnika do swoich potrzeb. (Dla wyników może być potrzebny konkretny typ zamiast anonimowego typu - w rzeczywistości go nie testowałem).

+0

Dzięki, ale który porównań? Czy istnieje ogólny sposób tworzenia porównywania, który pasuje do dowolnej sortowania SQL Server, czy możesz pokazać mi kod do porównywania jak SQL_Latin1_General_CP_CI_AI? –

+0

Nie wierzę, że jest nieoczekiwane IComparer do sortowania SQL Server. Musisz utworzyć klasę, która implementuje program IComparer, i samodzielnie dokonać odpowiednich porównań. – Brett

+0

(cd ..) Nie mówię, że to będzie ładne :) Oczywiście, jeśli konkretnie chcesz SQL_Latin1_General_CP1_CI_AI, możesz wykonać ToLower() (CI). Chyba szukanie/zamiana akcentów (AI)? To trochę dalej niż badałem ... – Brett

1

Napisz niestandardową implementację IComparer, która faktycznie wywołuje serwer SQL, aby porównać każdą z dwóch wartości, które ma porównać.

Byłoby bardzo wolno, trochę głupio, ale zrobiłoby dokładnie to, o co prosisz.

Jeśli zależy Ci tylko na dokładnej replikacji jednej konkretnej sekwencji sortowania, a nie na losowym sortowaniu, napisz jednorazową procedurę, aby wywołać SQL Server i zbuduj kolekcję wszystkich znaków w kolejności na serwerze SQL wstawi je i użyje do zbudowania niestandardowej implementacji IComparer, która następnie dopasuje sekwencję serwera SQL bez wywoływania do serwera SQL w czasie wykonywania.

+0

dzięki za odpowiedź. Szkoda, że ​​nie mogłem tego dwa razy zrobić. Oznaczę to jako akceptowaną odpowiedź, ale odpowiedź Remusa Rusanu właściwie postawiła mnie na właściwej ścieżce - co według mnie jest właściwym sposobem na poradzenie sobie z tymi wszystkimi problemami - stworzenie własnych danych w czystej bazie danych lub robi to w transakcji i cofa się po zakończeniu testu. –

Powiązane problemy