如何检查表中每行有70多列的完全匹配?

时间:2013-04-16 18:59:19

标签: .net linq duplicates

在过去的十年里,我被卷入了一个被黑客攻击的项目中。只是为了让它知道:我已经建议并询问我们是否可以在继续开发之前重构数据库并检查系统的架构设计,但是多个较小的项目可交付成果比修复当前系统中的缺陷“更重要”

话虽如此,如果确切匹配,检查代码的最佳方法是什么?

假设此表中有75列,超过200万行。

我知道我能做到:

var foo = bar.GetNewDocument();
dbContext.documents.Count(p => p.firstCol == foo.firstCol
                            && p.secondCol == foo.secondCol
                            && etc, etc);

这显然不是最好的解决方案......有没有更好的方法将这个新条目在代码中与其他条目进行比较以检查匹配?

2 个答案:

答案 0 :(得分:0)

使用HashSet<int>,在文档类中编写自定义哈希方法

HashSet<int> hashes...;
dbContext.documents.ToList().ForEach(d=>{
  if (hashes.Contains(d.GetHash()))
    Console.WriteLine("Found one: "+d); // do further comparison here to ensure it's not hash collision
  else
    hashes.Add(d.GetHash());
});

请注意,如果dbContext.documents包含太多条目,则应使用foreach而不是.ToList,因为ToList会立即将它们全部拉下来。

如果您不使用.ToList()并尝试直接使用它,例如dbContext.documents.Any(d=>d.GetHash()...),则无法访问哈希方法 - 这将无效,因为它无法翻译进入SQL

如果经常执行此操作,您可以(!)添加另一个包含哈希的列(或添加一个包含它的表),这样反复检查的开销将非常小 - SQLServer可以检查2百万行非常快速地在索引列中。

答案 1 :(得分:0)

如果要进行sql查询,则需要构建表达式。例如:

    public static Expression<Func<T, bool>> GetEqualsExpression<T>(T obj)
    {
        var type = typeof (T);

        var x = Expression.Parameter(type, "x");

        BinaryExpression body = null;
        foreach (var propertyInfo in type.GetProperties())
        {
            var left = Expression.Property(x, propertyInfo);
            var right = Expression.Constant(propertyInfo.GetValue(obj, null));
            var equalsExpression = Expression.Equal(left, right);

            body = body == null ? equalsExpression : Expression.AndAlso(body, equalsExpression);
        }

        return Expression.Lambda<Func<T, bool>>(body, x);
    }

用法

        var foo = bar.GetNewDocument();
        var expression = GetEqualsExpression(foo);
        dbContext.documents.Count(expression);