Linq to 实体有时会将重复的条目插入到数据库中
本文关键字:插入 数据库 实体 to Linq | 更新日期: 2023-09-27 18:30:57
下面的代码用于向数据库添加一行或更新已经存在的行。
IEnumerable<Guid> fieldIds = glen.ComplianceField.Select(field => field.id);
ComplianceData data;
foreach (Guid fieldId in fieldIds)
{
if (!checkEntity(fieldId, Extra.grn))
{
if (collection[fieldId.ToString()] != null)
{
if (glen.ComplianceData.Where(compData => (compData.fieldId == fieldId) && (compData.grn == Extra.grn)).Count() == 0)
{
data = new ComplianceData();
glen.ComplianceData.Add(data);
}
else
data = glen.ComplianceData.First(compData => (compData.fieldId == fieldId) && (compData.grn == Extra.grn));
data.fieldId = fieldId;
data.grn = Extra.grn;
data.value = collection[fieldId.ToString()];
}
}
}
glen.SaveChanges();
但是,有时(我怀疑用户是否多次单击提交按钮)该行在数据库中重复(如果服务器特别慢,则多次重复)。 此问题仅在首次创建条目时发生,之后第一个条目将按预期更新。
我尝试使用上下文的 ChangeTracker 属性,但我怀疑这不起作用,因为 glen 上下文在每个连续请求中都是不同的对象。 有没有办法在执行操作时锁定数据库表,或者在刚刚发出相同请求时阻止操作执行数据库更新?
如果您怀疑这是由于按钮的多次提交单击,那么您可以采取各种步骤来阻止此操作,例如在按钮被激活后立即禁用它。您还应该进行一些服务器端检查,以确保没有收到多个请求。
我终于设法使用 System.Transactions
做到这一点(我必须添加一个新引用才能访问它)。 我最后的片段是——
IEnumerable<Guid> fieldIds = glen.ComplianceField.Select(field => field.id);
ComplianceData data;
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = System.Transactions.IsolationLevel.Serializable}))
{
foreach (Guid fieldId in fieldIds)
{
if (collection[fieldId.ToString()] != null)
{
if (glen.ComplianceData.Where(compData => (compData.fieldId == fieldId) && (compData.grn == Extra.grn)).Count() == 0)
{
data = new ComplianceData();
glen.ComplianceData.Add(data);
}
else
data = glen.ComplianceData.First(compData => (compData.fieldId == fieldId) && (compData.grn == Extra.grn));
data.fieldId = fieldId;
data.grn = Extra.grn;
data.value = collection[fieldId.ToString()];
}
}
glen.SaveChanges();
scope.Complete();
}
部分归功于这个答案 https://stackoverflow.com/a/13097278/1173776