我们有一个db模型Vote
,我们已经使用了一段时间,最近添加了一个ndb模型Score
,它代表实体的累积分数,基于其投票。目前Score
是其投票的父级,因为我们希望它们都在同一个实体组中(因此可以在同一个事务中更新它们)。我一直在努力让一个可以更新Vote
和Score
的交易,但它一直都会失败。这是一些示例代码:
def transaction():
score = self.key_score.get()
vote = db.get(self.key_vote)
# do stuff
score.put()
vote.put()
db.run_in_transaction(transaction)
据我所知(仅限dev服务器),这总是重试四次:
WARNING:root:Transaction collision. Retrying...
WARNING:root:Transaction collision. Retrying...
WARNING:root:Transaction collision. Retrying...
WARNING:root:Transaction collision. Retrying...
ERROR
然后我得到“TransactionFailedError:交易无法提交。请再试一次。”。
我已经尝试了一些方法来解决这个问题:
更改获取和放置的顺序 - 我想也许有一个实体组锁定问题,我不明白但是切换获取或放置的顺序并没有改变行为。< / p>
异步投放。这实际上就是我开始的 - 我知道同时放置db和ndb模型的唯一方法(我认为这实际上是在幕后放置多个键的原因)。结果相同。
score_future = score.put_async()
vote_future = db.put_async(vote)
score_future.get_result()
vote_future.get_result()
将db.run_in_transaction
替换为ndb.transaction
。这会引发“AttributeError:'Key'对象在db.get
上没有属性'reference'”。我不确定这里发生了什么 - 看起来一些幕后代码正在db.Key
预期ndb.Key
。
有趣的是,如果删除parent
关系,我可以运行与上面相同的代码,这意味着实体不在同一个实体组中。
那么,是否可以在同一个实体组中同时使用db和ndb模型?也许有一种简单的方法可以将db模型作为ndb,反之亦然?
答案 0 :(得分:5)
所有实体与数据存储区看起来相同,无论它们是使用DB还是NDB创建的。这里的问题是你试图在API调用中混合两者; db在传递ndb模型实例时不知道该怎么做。
您需要创建一个与您的投票数据库模型相同的NDB模型 - 或者更好的是,将Vote迁移到NDB模型 - 并在需要两种实体类型的事务的任何代码中使用它。