比较 PonyORM 中的实体实例

Comparing entity instances in PonyORM

我正在尝试比较 identity/equality 的 PonyORM 实体实例。考虑以下代码,使用 estore 示例数据库:

from pony.orm import *
from pony.orm.examples.estore import *

# Test 1
with db_session:
    a = Customer[1]
    b = Customer[1]
print(a is b, a == b)    # True True

# Test 2
with db_session:
    a = Customer[1]
with db_session:
    b = Customer[1]
print(a is b, a == b)    # False False

当且仅当在相同的 db_session.

中检索时,具有相同主键的实体测试为相同且相等
  1. 这种行为背后的基本原理是什么? (来自文档:如果具有指定主键的对象已经加载到 db_session() 缓存中,Pony returns 从缓存中获取对象而不向数据库发送查询。 这解释了身份测试的结果。我仍然希望在测试 1 和 2 中看到相等。)

  2. 测试相等性的推荐方法是什么(比较主键除外)?

What is the rationale behind this behaviour?

最初 Pony 希望您只使用 db_session 中的对象。所以 - 一旦 db_session 结束,您不应该使用这些对象。这是为什么 - 您可以将 db_session 视为交易。因此,如果您使用两个不同的 db_sessions,您将使用不同的事务,这意味着无法保证这两个对象在逻辑上是一致的。

为什么Pony允许你在db_session之后使用对象?因为有些开发者想把应用层和数据库层分开,在db_session结束后渲染HTML个模板。

其实Pony认为正确的方法是在db_session内渲染模板,但是要求太高,所以Pony同意了。但无论如何,混合其他两个 db_sessions 的对象是完全错误的方式,Pony 不希望你这样做。

What is the recommended way to test for equality?

如果您仍想比较来自不同 db_sessions 的对象,我建议您使用这样的函数

def equals(a, b):
    if isinstance(a, pony.orm.core.Entity):
        return type(a) == type(b) and a.get_pk() == b.get_pk()
    return a == b

with db_session:
    a = Customer[1]
with db_session:
    b = Customer[1]
print(a is b, a == b, equals(a, b))    # False, False, True