避免在数据库中添加重复项的最佳方法

ini*_*iki 2 c# sql-server hashset

我有一个包含三列的SQL Server表:

表格1

col1 int
col2 int
col3 string
Run Code Online (Sandbox Code Playgroud)

我为所有三列定义了一个唯一约束 (col1, col2, col3)

现在,我有一个.csv文件,我想在此表中添加记录,*.csv文件可以有重复记录.

我在上面的场景中搜索了各种避免重复的选项.以下是适合我的三个选项.请看一下并提出一些关于每种方法的优点/缺点的想法,以便我可以选择最好的方法.

选项1 :

首先避免重复,即从csv文件向列表添加对象时.我用过HashSet<T>了这个并覆盖了类型T下面的方法:

public override int GetHashCode()
{
    return col1.GetHashCode() + col2.GetHashCode() + col3.GetHashCode();
}

public override bool Equals(object obj)
{
    var other = obj as T;
    if (other == null)
    {
        return false;
    }
    return col1 == other.col1
        && col2 == other.col2
        && col3 == other.col3;
}
Run Code Online (Sandbox Code Playgroud)

选项#2

List<T>代替HashSet<T>.

添加所有对象后删除重复项 List<T>

    List<T> distinctObjects = allObjects
        .GroupBy(x => new {x.col1, x.col2, x.col3})
        .Select(x => x.First()).ToList();
Run Code Online (Sandbox Code Playgroud)

选项#3

添加所有对象后删除重复项DataTable.

public static DataTable RemoveDuplicatesRows(DataTable dataTable)
{
    IEnumerable<DataRow> uniqueRows = dataTable.AsEnumerable().Distinct(DataRowComparer.Default);
    DataTable dataTable2 = uniqueRows.CopyToDataTable();
    return dataTable2;
}
Run Code Online (Sandbox Code Playgroud)

虽然我还没有比较他们的运行时间,但我更喜欢选项#1,因为我正在删除重复项作为第一步 - 所以只需要按照要求进行操作.

请分享您的观点,以便我选择最好的观点.

非常感谢!

Tim*_* S. 5

我喜欢选项1:它HashSet<T>提供了一种避免重复的快速方法,然后再将它们发送到数据库.你应该实现一个更好的GetHashCode,例如使用Skeet的实现,什么是重写的System.Object.GetHashCode的最佳算法?

但是有一个问题:如果表中已包含可能与CSV重复的数据,该怎么办?你必须首先复制整个表格,以便简单HashSet地工作.你可以做到这一点,但为了解决这个问题,我可能会将选项1与临时表和插入语句配对,例如Skip-over /忽略insert上重复行:

INSERT dbo.Table1(col1, col2, col3)
SELECT col1, col2, col3 
FROM dbo.tmp_holding_Table1 AS t
WHERE NOT EXISTS (SELECT 1 FROM dbo.Table1 AS d
WHERE col1 = t.col1
AND col2 = t.col2
AND col3 = t.col3);
Run Code Online (Sandbox Code Playgroud)

通过这种组合,可以最大限度地减少传输到数据库或从数据库传输的数据量.