2013-02-23 3 views
-1

я получаю повторяющиеся строки при использовании следующим:Четкий способ повторить данные

DataTable dt = list.AsEnumerable().Distinct().CopyToDataTable(); 

Почему Distinct() не работает?


Моя DataTable структура:

serial,doc_content,doc_name,selected 
int ,Byte[]  ,string ,int 
+3

Что такое 'list'? Что находится внутри 'list'? Попробуйте использовать 'list.Distinct(). AsEnumerable(). CopyToDataTable(); ' – nemesv

+0

' var list = dt_temp.Select ("selected = 1"); ' –

+0

' int, byte [], string, int' –

ответ

2

Distinct будет сравнивать ссылки на объект, так как DataRow не переопределить значение по умолчанию Equals и GetHashCode методы из object принимать в расчет значение, хранящееся в строках.

Существует перегрузка Enumerable.Distinct, что дает вам возможность указать ваш собственный аналог равенства, и существует класс DataRowComparer, который реализует необходимый интерфейс IEqualityComparer<DataRow>.

Вы можете использовать его как это:

var distinct = list.AsEnumerable() 
    .Distinct(DataRowComparer.Default) 
    .CopyToDataTable(); 
+0

Ну 'Distinct()' будет вызывать 'GetHashCode' и' Equals'. Это только сравнение «по ссылке» здесь, потому что 'DataRow' не переопределяет' Equals'. –

+1

Я не знал о DataRowComparer.Default before - nice. Не уверен, будет ли он работать с полем 'byte []'; это зависит от того, как он хранится внутри страны. –

2

Вы звоните Distinct() на последовательности строк данных. Я не верю DataRow переопределяет Equals, так что любые два объекта DataRow сравниваются как неравномерные.

Вам необходимо либо передать IEqualityComparer<DataRow>, либо Distinct(), либо сначала проецироваться в другой тип (например, анонимный тип, который уже реализует сравнение равенства), и вызывать Distinct() в новой последовательности.

Если вы хотите продолжать работать с DataRow, это, вероятно, проще всего реализовать сравнительный коэффициент равенства. Хотя DataRowComparer.Defaultвыглядит перспективным (об этом я раньше не знал) может не работает в вашем конкретном случае из-за поля byte[].

Лично мне нравится получать данные в более конкретные типы как можно быстрее, но YMMV. Обратите внимание, что если вы спроецировать весь DataTable к более конкретному типу, вы могли бы написать Select части как Where пункта вместо:

var list = table.AsEnumerable() 
    .Select(row => new { Serial = row.Field<string>("serial"), 
          ContentBase64 = Convert.ToBase64String(row.Field<byte>("doc_content")), 
          Name = row.Field<string>("doc_name"), 
          Selected = row.Field<int>("selected") }) 
    .Where(x => x.Selected == 1) 
    .Distinct() 
    .ToList(); 

Обратите внимание, что я преобразующее содержимое в строку base64, так что сравнение равенства будет работайте просто. Это не самый эффективный подход, но он is easy :) Если вам не нужен контент, вы можете избавиться от этого фрагмента проекции.

+0

Не могли бы вы дать мне пример, как это сделать? –

+1

@just_name: см. Мое редактирование (для проекционной версии). –

+0

Есть ли способ использовать 'CopyToDataTable();' после этого –

Смежные вопросы