【问题标题】:How to maintain unique List Before Saving To Database? - C#保存到数据库之前如何维护唯一列表? - C#
【发布时间】:2010-11-16 00:21:09
【问题描述】:

一个简化的场景:

  • 我有一个List<Foo>
  • Foo 有两个属性 Description (string), IsFoo (bool)

例如:

var foos = new List<Foo>();

用户可以通过文本框“添加新的 Foo”,然后在表单提交时我这样做:

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

但是,有多个文本框,例如,如果他们在文本框一中输入“FooBar”,然后在文本框二中输入“FooBar”,我不想显示错误,但我只是不想将它们添加到集合中。 (不用担心背后的原因,这是一个简化的场景)。

我不需要向 UI 显示任何内容,就在他们提交表单时,在持久保存到数据库之前,我需要删除任何重复项(或首先阻止它们被添加到列表中)。

最简单/最好的方法是什么?也许是字典?

我正在使用 C#4、LINQ、.NET 4。

【问题讨论】:

    标签: c# .net linq list collections


    【解决方案1】:

    您可以使用HashSet&lt;Foo&gt;

    HashSet 是唯一的、无序的集合。
    添加一个已经存在的元素不会默默地做任何事情。 (并返回false

    请注意,您必须覆盖 Foo 类上的 EqualsGetHashCode 以按值进行比较。

    还要注意哈希集本质上是无序的;如果您关心广告订单,则不能使用它。


    或者,您可以使用 LINQ 检查您的列表是否有重复:

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

    【讨论】:

    • 是的,问题是“Foo”实际上是一个用于持久性的 POCO(虽然不是直接),所以我真的不想向它添加额外的元数据(即使它是通过部分的)。 “替代方案”可以工作 - 但我在页面上也有一个转发器,我正在使用 AddRange 添加项目,不知道如何将 Any 应用到 AddRange
    • 我最终将您的“替代”放入扩展方法(以及另一个用于 addrange)中,然后调用它。谢谢。
    • @RPM:您可以调用 Where 来调整您正在添加的项目,并且只传递那些不存在的项目。
    【解决方案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&lt;Foo&gt; 中,如下所示:

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

    使用此代码,如果将第二个 Foo 对象添加到哈希集中并且与哈希集中已经存在的对象具有相同的描述,则根本不会添加新对象。

    【讨论】:

    • 伙计,你最近无处不在,9 天内 183 个回答,想知道是否有徽章。 :)
    • 你不会处理有趣的 Unicode 字符。相反,return String.Equals(a.Description, b.Description, StringComparison.OrdinalIgnoreCase)return StringComparer.OrdinalIgnoreCase.GetHashCode(obj.Description)
    • @RPM1984:是的……我来这里的八天里,代表人数上限,上周最活跃的新用户是代表,上周是第七位最活跃的用户。我需要休息一下什么的。也许偶尔出去一次。
    【解决方案3】:

    你可以在 linq 中使用 Distinct 吗?

    这是 VB(不准确,因为我在这台机器上没有 VS),但大致如下:

    Dim ie as IEnumerable(of Foo) = From obj As Foo In Foo's Select obj Distinct

    然后实现IEqualityComparer? - 看起来@cdhowie 刚刚回答了......

    【讨论】:

      猜你喜欢
      • 2015-08-31
      • 2012-10-26
      • 2015-06-16
      • 2014-02-01
      • 2011-06-11
      • 1970-01-01
      • 2015-05-16
      • 1970-01-01
      相关资源
      最近更新 更多