想象一下这种情况:

  • 实体上的有序集合。
  • 对集合
  • 中的新项目的两个同时(异步)CREATE请求
  • 两个新项目均获得相同的序数。

  • 该集合是这样的:
    public virtual IList<CustomField> CustomFields { get; protected set; }
    

    我有流利的nhibernate映射,如下所示:
    mapping.HasManyToMany(cp => cp.CustomFields)
                .AsList(i => i.Column("CustomFieldOrdinal"))
                .ParentKeyColumn("RegistrationId")
                .ChildKeyColumn("CustomFieldId");
    

    原因是nhibernate正在查询db以获取下一个可用的序数,并且表上没有锁,并且两者都获取了相同的序数。

    如何预防?

    最佳答案

    db中唯一的索引/约束将解决此问题。当然,您将不得不处理两个请求之一的刷新失败。

    如果要避免在应用程序端处理异常,则可以改为(此外)对持有列表(ISession.Lock(entity, LockMode.Upgrade))的实体发出排他的db锁定,然后再读取(或从db刷新)其列表状态。然后,更新列表。
    如果所有插入列表的应用程序都遵循相同的模式,则它们将无法同时插入具有相同索引的元素:它们将等待释放锁,然后将新数据放入db中,然后再读取它并插入自己的新元素。
    这是一个pessimistic concurrency pattern。阅读更多here too(此other answer上的链接)。

    乐观的人需要使用行版本列,并确保任何列表更新都与实体版本相关。但是,如果是并发,则两个请求之一将有一个并发异常。

    关于database - Nhibernate IList(有序列表)竞争条件,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36604751/

    10-17 02:36