保证不插入重复记录?
Guarantee a duplicate record is not inserted?
我有一些插入记录的代码,我想先删除所有具有匹配元组的现有记录。从许多可执行文件中快速调用此代码:
public void AddMemberEligibility(long memberId, string internalContractKey, int planSponsorId, int vendorId, string vendorContractKey) {
using (IDocumentSession session = Global.DocumentStore.OpenSession()) {
var existingMember = session.Query<MemberEligibility>().FirstOrDefault(x => x.VendorId == vendorId
&& x.MemberId == memberId && x.PlanSponsorId == planSponsorId);
if (existingMember != null) {
session.Delete<MemberEligibility>(existingMember);
session.SaveChanges();
}
Eligibility elig = new Eligibility() {
InternalContractKey = internalContractKey,
MemberId = memberId,
PlanSponsorId = planSponsorId,
VendorId = vendorId
};
session.Store(elig);
session.SaveChanges();
}
}
这似乎不足以防止重复。有什么建议吗?
哈希集合可以很好地解决这个问题。
它在输入时调用 hashCode() 并包含使集合保持一定组织性的函数,然后使用 equals() 来测试重叠的哈希码。这种组合使它的 put 和 contains 函数通常为 0(1);尽管如果说所有哈希码都相同,那么它会将包含增加到 0(logn)。
很可能并发哈希集合更可取。如果你在 java(看起来像),你可以使用 CurrentHashSet
在听取了 Oren Eini 关于 Raven Google 组的建议后,我最终做的是使用 Unique Constraints Bundle。
我的 DTO 现在看起来像这样:
using Raven.Client.UniqueConstraints;
public class MemberEligibility {
[UniqueConstraint]
public string EligibilityKey { get { return $"{MemberId}_{VendorId}_{PlanSponsorId}_{VendorContractKey}"; } }
public long MemberId { get; set; }
public int VendorId { get; set; }
public int PlanSponsorId { get; set; }
public string VendorContractKey { get; set; }
// other fields
}
我的 add/update 看起来像这样:
public void AddMemberEligibility(long memberId, int planSponsorId, int vendorId, string vendorContractKey, ...) {
using (IDocumentSession session = Global.DocumentStore.OpenSession()) {
MemberEligibility elig = new MemberEligibility() {
MemberId = memberId,
PlanSponsorId = planSponsorId,
VendorId = vendorId,
VendorContractKey = vendorContractKey,
//other stuff
};
var existing = session.LoadByUniqueConstraint<MemberEligibility>(x => x.EligibilityKey, elig.EligibilityKey);
if (existing != null) {
// set some fields
} else {
session.Store(elig);
}
session.SaveChanges();
}
}
在这一点上,我不能 100% 确定这是我将投入生产的解决方案,但它确实有效。请记住,如果商店中已经存在具有相同 [UniqueConstraint]
属性 的文档,session.SaveChanges()
将抛出异常。此外,我开始将此 属性 键入为 Tuple<...>
,但 Raven 的序列化程序无法弄清楚如何使用它,所以我暂时选择了 string
。
我有一些插入记录的代码,我想先删除所有具有匹配元组的现有记录。从许多可执行文件中快速调用此代码:
public void AddMemberEligibility(long memberId, string internalContractKey, int planSponsorId, int vendorId, string vendorContractKey) {
using (IDocumentSession session = Global.DocumentStore.OpenSession()) {
var existingMember = session.Query<MemberEligibility>().FirstOrDefault(x => x.VendorId == vendorId
&& x.MemberId == memberId && x.PlanSponsorId == planSponsorId);
if (existingMember != null) {
session.Delete<MemberEligibility>(existingMember);
session.SaveChanges();
}
Eligibility elig = new Eligibility() {
InternalContractKey = internalContractKey,
MemberId = memberId,
PlanSponsorId = planSponsorId,
VendorId = vendorId
};
session.Store(elig);
session.SaveChanges();
}
}
这似乎不足以防止重复。有什么建议吗?
哈希集合可以很好地解决这个问题。
它在输入时调用 hashCode() 并包含使集合保持一定组织性的函数,然后使用 equals() 来测试重叠的哈希码。这种组合使它的 put 和 contains 函数通常为 0(1);尽管如果说所有哈希码都相同,那么它会将包含增加到 0(logn)。
很可能并发哈希集合更可取。如果你在 java(看起来像),你可以使用 CurrentHashSet
在听取了 Oren Eini 关于 Raven Google 组的建议后,我最终做的是使用 Unique Constraints Bundle。
我的 DTO 现在看起来像这样:
using Raven.Client.UniqueConstraints;
public class MemberEligibility {
[UniqueConstraint]
public string EligibilityKey { get { return $"{MemberId}_{VendorId}_{PlanSponsorId}_{VendorContractKey}"; } }
public long MemberId { get; set; }
public int VendorId { get; set; }
public int PlanSponsorId { get; set; }
public string VendorContractKey { get; set; }
// other fields
}
我的 add/update 看起来像这样:
public void AddMemberEligibility(long memberId, int planSponsorId, int vendorId, string vendorContractKey, ...) {
using (IDocumentSession session = Global.DocumentStore.OpenSession()) {
MemberEligibility elig = new MemberEligibility() {
MemberId = memberId,
PlanSponsorId = planSponsorId,
VendorId = vendorId,
VendorContractKey = vendorContractKey,
//other stuff
};
var existing = session.LoadByUniqueConstraint<MemberEligibility>(x => x.EligibilityKey, elig.EligibilityKey);
if (existing != null) {
// set some fields
} else {
session.Store(elig);
}
session.SaveChanges();
}
}
在这一点上,我不能 100% 确定这是我将投入生产的解决方案,但它确实有效。请记住,如果商店中已经存在具有相同 [UniqueConstraint]
属性 的文档,session.SaveChanges()
将抛出异常。此外,我开始将此 属性 键入为 Tuple<...>
,但 Raven 的序列化程序无法弄清楚如何使用它,所以我暂时选择了 string
。