保证没有插入重复记录?

时间:2017-04-26 13:53:59

标签: c# ravendb

我有一些插入记录的代码,我想先删除任何匹配元组的现有记录。从许多可执行文件中快速调用此代码:

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();
    }
}

这似乎不足以防止重复。有什么建议吗?

2 个答案:

答案 0 :(得分:0)

哈希集合可以很好地解决这个问题。

它在输入上调用hashCode()并包含保持集合有点组织的函数,然后使用equals()来测试重叠的哈希码。这种组合使得它的放置和包含函数通常为0(1);虽然如果说所有哈希码都相同,那么它增加包含为0(logn)。

最有可能的是并发哈希集合。如果你在java(它看起来像),你可以使用CurrentHashSet

答案 1 :(得分:0)

在采用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
}

我的添加/更新如下所示:

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%肯定这是我将推向生产的解决方案,但它确实有效。请记住,session.SaveChanges()如果商店中已存在具有相同[UniqueConstraint]属性的文档,则会抛出异常。此外,我开始使用Tuple<...>键入此属性,但Raven的序列化程序无法弄清楚如何使用它,所以我现在确定了string