在性能方面检查重复实体的好方法是什么
What is a good way in terms of performance to check duplicate entity
我需要在将实体保存到数据库之前检查重复条目。下面是我当前的代码
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 调用来验证实体。此 table 有数百万条记录,此应用程序将被数千名用户使用。所以它会严重损害性能。不过我可以让它成为一个查询
if (db.Product.Any(x => x.Code == entity.Code || x.Name == entity.Name || x.OtherField == entity.OtherField))
{
error.Add('Duplication found');
}
第二个代码的问题是我不知道哪个字段是重复的。
这样做的更好方法是什么?我应该只依赖于数据库中的唯一约束吗?但是来自数据库的错误很难看。
编辑
如果超过 1 个重复字段,我需要向用户显示所有错误。
考虑场景:如果重复字段是代码和名称。如果我告诉用户代码已经存在,那么他会更改代码并再次尝试保存。然后显示第二个错误(名称字段)。它使用户在成功保存之前点击保存几次。
1- 您可以 select 复制实体
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();
这将 select 每个重复字段的数量。
需要注意的一件事:无论如何,您应该在数据库中具有唯一约束,因为在您验证和保存数据时,可能会在您插入之前插入具有这些值的另一行。
你可以这样做:
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>
}
如果你在Name
、Code
、OtherField
字段上有索引,那么重复检查不会太长,但仍然是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");
我需要在将实体保存到数据库之前检查重复条目。下面是我当前的代码
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 调用来验证实体。此 table 有数百万条记录,此应用程序将被数千名用户使用。所以它会严重损害性能。不过我可以让它成为一个查询
if (db.Product.Any(x => x.Code == entity.Code || x.Name == entity.Name || x.OtherField == entity.OtherField))
{
error.Add('Duplication found');
}
第二个代码的问题是我不知道哪个字段是重复的。
这样做的更好方法是什么?我应该只依赖于数据库中的唯一约束吗?但是来自数据库的错误很难看。
编辑
如果超过 1 个重复字段,我需要向用户显示所有错误。 考虑场景:如果重复字段是代码和名称。如果我告诉用户代码已经存在,那么他会更改代码并再次尝试保存。然后显示第二个错误(名称字段)。它使用户在成功保存之前点击保存几次。
1- 您可以 select 复制实体
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();
这将 select 每个重复字段的数量。 需要注意的一件事:无论如何,您应该在数据库中具有唯一约束,因为在您验证和保存数据时,可能会在您插入之前插入具有这些值的另一行。
你可以这样做:
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>
}
如果你在Name
、Code
、OtherField
字段上有索引,那么重复检查不会太长,但仍然是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");