在检查重复实体的性能方面有什么好方法

时间:2015-01-13 06:52:37

标签: c# sql-server entity-framework entity-framework-6

在将实体保存到数据库之前,我需要检查重复的条目。以下是我目前的代码

if (db.Product.Any(x => x.Code == entity.Code))
{
  error.Add('Duplicate code');
}

if (db.Product.Any(x => x.Name == entity.Name))
{
  error.Add('Duplicate name');
}

if (db.Product.Any(x => x.OtherField == entity.OtherField))
{
  error.Add('Duplicate other field');
}

上面代码的问题是它对验证实体进行了3 db调用。这个表有数百万条记录,这个应用程序将被千名用户使用。所以它会严重损害性能。我可以通过

进行一次查询
if (db.Product.Any(x => x.Code == entity.Code || x.Name == entity.Name || x.OtherField == entity.OtherField))
{
  error.Add('Duplication found');
}

第二个代码的问题是我不知道哪个字段是重复的。

这样做的更好方法是什么?我应该只依赖数据库中的唯一约束吗?但是,数据库中的错误很难看。

修改

如果超过1个重复字段,我需要向用户显示所有错误。 考虑这种情况:如果重复的字段是代码和名称。如果我告诉用户代码已经存在,那么他会更改代码并尝试再次保存。然后显示第二个错误(名称字段)。在成功保存之前,它会使用户点击保存几次。

3 个答案:

答案 0 :(得分:2)

如果您在字段NameCodeOtherField上有索引,则重复检查不会太长,但仍会是对数据库的3次调用,而不是1次。

在这种情况下,通常的解决方案是重复计算。然后,如果count等于0,则不会重复。

Here你会发现一些黑客攻击。

简短的例子:

var counts =(
    from product in db.Products
    group product by 1 into p
    select new
    {
        Name = p.Count(x => x.Name == name),
        Code = p.Count(x => x.Code == code),
        OtherField = p.Count(x => x.OtherField == otherFields)
    }
).FirstOrDefault();

if (counts.Name > 0)
    error.Add("Duplicate name");

if (counts.Code > 0)
    error.Add("Duplicate code");

更新:似乎可以通过更简单的方法解决问题:

var duplicates =(
    from product in db.Products
    group product by 1 into p
    select new
    {
        Name = p.Any(x => x.Name == name),
        Code = p.Any(x => x.Code == code),
        OtherField = p.Any(x => x.OtherField == otherFields)
    }
).FirstOrDefault();

if (duplicates.Name)
    error.Add("Duplicate name");

答案 1 :(得分:1)

您可以这样做:

    string duplicateField;

    bool validationResult = db.Product.Any(x => {
            if(x.Code == entity.Code){
            duplicateField = "Code";
                return true;
            }
    // Other field checks here

}

if(validationResult){
// Error in field <duplicateField>
}

答案 2 :(得分:0)

1-您可以选择重复实体

var product = db.Product.FirstOrDefault(x => x.Code == entity.Code
                                               || x.Name == entity.Name
                                               || x.OtherField == entity.OtherField);

if (product == null)
;//no duplicates

if (product.Code == entity.Code)
{
  error.Add('Duplicate code');
}

if (product.Name == entity.Name)
{
  error.Add('Duplicate name');
}

if (product.OtherField == entity.OtherField)
{
  error.Add('Duplicate other field');
}

2-您可以创建插入的存储过程并检查其中的重复项;

编辑: 好的,你可以写这样的东西

    var duplicates = (from o in db.Products
              select new
              {
                  codeCount = db.Products.Where(c => c.Code == entity.Code).Count(),
                  nameCount = db.Products.Where(c => c.Name == entity.Name).Count(),
                  otherFieldCount = db.Products.Where(c => c.OtherField == entity.OtherField).Count()
              }).FirstOrDefault();

这将按字段选择每个重复的数量。 有一点需要注意:无论如何,您应该在数据库中有唯一的约束,因为在验证和保存数据时,可能会在插入之前插入具有这些值的另一行。