2010-11-16 3 views
1

упрощенный сценарий:Как сохранить уникальный список перед сохранением базы данных? - C#

  • У меня есть List<Foo>.
  • Foo имеет два свойства Описание (строка) IsFoo (BOOL)

Например:

var foos = new List<Foo>(); 

Пользователь может "добавить новый Foo в" с помощью текстовых полей, то on form submit Я делаю это:

foos.Add(new Foo { Description = txtOne.Text, IsFoo = true }); 
foos.SaveToDb(); 

Однако есть несколько Textboxes, и если, например, они печатают «FooBar» в текстовом поле один, то «FooBar» в текстовом поле два, я не хочу, чтобы показать ошибку, но я просто не хочу чтобы добавить их в коллекцию. (не беспокойтесь о причине этого, это упрощенный сценарий).

Мне не нужно ничего показывать в пользовательском интерфейсе, только когда они отправляют форму, прежде чем оставаться в базе данных, мне нужно удалить любые дубликаты (или предотвратить их добавление в список в первую очередь).

Какой самый простой/лучший способ сделать это? Возможно, словарь?

Я использую C# 4, LINQ, .NET 4.

ответ

3

Вы можете использовать HashSet<Foo>.

HashSets - уникальные, неупорядоченные коллекции.
Добавление элемента, который уже существует, беззвучно ничего не сделает. (И вернуть false)

Обратите внимание, что вы необходимо переопределение Equals и GetHashCode на Foo класса для сравнения по значению.

Также обратите внимание на то, что хешеты являются внутренне неупорядоченными; если вам нужен порядок вставки, вы не сможете его использовать.


В качестве альтернативы, вы можете использовать LINQ, чтобы проверить, имеет ли ваш список дубликат:

if (!foos.Any(f => f.Description == txtOne.Text)) 
    foos.Add(new Foo { Description = txtOne.Text, IsFoo = true }); 
+0

Да, проблема в том, что «Foo» на самом деле является POCO, используемым для сохранения (не напрямую), поэтому я действительно не хочу добавлять к нему дополнительные метаданные (даже если это через частичный). «Альтернатива» будет работать, но у меня также есть ретранслятор на странице, и я использую 'AddRange' для добавления элементов, а не уверен, как применять' Any' к 'AddRange'. – RPM1984

+0

Я закончил тем, что поместил вашу «альтернативу» в метод расширения (и еще один для addrange) и назвал это. Благодарю. – RPM1984

+0

@RPM: Вы бы назвали 'Where', чтобы убрать элементы, которые вы добавляете, и пропускать только те, которые еще не существуют. – SLaks

2

Чтобы расширить на ответ SLaks', вы могли бы сделать что-то вроде этого:

public class FooComparer : IEqualityComparer<Foo> { 
    public static readonly FooComparer Instance = new FooComparer(); 

    private FooComparer() { } 

    public bool Equals(Foo a, Foo b) { 
     if (a == null) 
      return b == null; 

     if (b == null) 
      return false; 

     // For case-sensitivity: 
     return a.Description == b.Description; 

     // For case-insensitivity: 
     return String.Equals(a.Description, b.Description, StringComparison.OrdinalIgnoreCase); 
    } 

    public int GetHashCode(Foo obj) { 
     // For case-sensitivity: 
     return obj.Description.GetHashCode(); 

     // For case-insensitivity: 
     return StringComparer.OrdinalIgnoreCase.GetHashCode(obj.Description); 
    } 
} 

Затем сохраните ваши товары в HashSet<Foo> следующим образом:

var hashSet = new HashSet<Foo>(FooComparer.Instance); 
hashSet.Add(new Foo() { ... }); 

С помощью этого кода, если в hashset добавлен второй объект Foo и имеет такое же описание, как и уже существующее в hashset, новый объект просто не будет добавлен.

+1

Человек, которого вы были * повсюду * в последнее время, 183 ответа за девять дней, интересно, есть ли для этого значок. :) – RPM1984

+0

Вы не будете обрабатывать смешные символы Юникода. Вместо этого возвращаем String.Equals (a.Description, b.Description, StringComparison.OrdinalIgnoreCase) 'и' return StringComparer.OrdinalIgnoreCase.GetHashCode (obj.Description) '. – SLaks

+2

@ RPM1984: Да ... rep-capped за восемь полных дней, которые я здесь, самый активный новый пользователь на прошлой неделе по репутации, и 7-й наиболее активный пользователь на прошлой неделе по репутации. Мне нужно отдохнуть или что-то в этом роде. Может быть, выходите на улицу раз в то время. – cdhowie

0

Можете ли вы использовать Distinct в linq?

Это VB (и не точно, как я не получил VS на этой машине), но что-то вдоль линий:

Dim т.е., как IEnumerable (из Foo) = С OBJ Как Foo В Foo выберем obj Distinct

Затем внедрить IEqualityComparer? - смотри, как @cdhowie только что ответил ....

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