从SQLAlchemy会话中删除对象
我想把一个映射类的实例传递给一个不认识SQLAlchemy的方法(在另一个进程中),而我只需要我的属性值。问题是,每当这个方法想读取属性值时,就会出现一个UnboundExecutionError
的错误。我明白为什么会这样,但我希望能找到解决这个问题的方法。
我只需要我定义的属性值(在这个例子中是id、name和dirty),而不需要在目标方法中使用SQLAlchemy的那些复杂功能。
示例类:
Base = declarative_base()
class Record(Base):
__tablename__ = 'records'
_id = Column('id', Integer, primary_key=True)
_name = Column('name', String(50))
_dirty = Column('dirty', Boolean, index=True)
@synonym_for('_id')
@property
def id(self):
return self._id
@property
def name(self):
return self._name
@name.setter
def name(self, value):
self._name = value
self._dirty = True
name = synonym('_name', descriptor=name)
@synonym_for('_dirty')
@property
def dirty(self):
return self._dirty
示例调用:
...
def do_it(self):
records = self.query.filter(Record.dirty == True)
for record in records:
pass_to_other_process(record)
我尝试过使用session.expunge()
和copy.copy()
,但都没有成功。
3 个回答
0
你可能需要把这个对象变成临时状态:
这描述了一个对象在会话中可能拥有的主要状态之一;临时对象是一个新的对象,它没有任何数据库身份,也还没有和会话关联。当这个对象被添加到会话中时,它会变成待处理状态。
你可以通过删除旧对象,将其变为临时状态,然后用它来创建新对象。
类似于:
# Get the original object (new query style)
query = select(MyTable).where(MyTable.id == old_object_id)
results = session.execute(query)
old_object = result.scalar_one_or_none()
# Remove it from the session & make it transient
session.expunge(old_object)
make_transient(old_object)
# Use it to create the new object
new_object = MyTable(attr1=old_object.attr1 ...)
# Add & commit the new object
session.add(new_object)
session.commit()
20
你需要把SQL Alchemy对象从会话中移除,也就是所谓的“清除”。这样你就可以请求任何已经加载的属性,而不会让它试图重新使用它最后已知的会话或未绑定的会话。
self.expunge(record)
不过要注意,任何未加载的属性会返回它最后已知的值或者是None。如果你想以后再使用这个对象,可以再次调用“添加”或者“合并”。
self.add(record)
9
我猜测你遇到了SQLAlchemy的懒加载问题。因为我对SQLAlchemy的内部机制了解不多,所以我建议你这样做:
class RecordData(object):
__slots__ = ('id', 'name', 'dirty')
def __init__(self, rec):
self.id = rec.id
self.name = rec.name
self.dirty = rec.dirty
然后稍后...
def do_it(self):
records = self.query.filter(Record.dirty == True)
for record in records:
pass_to_other_process(RecordData(record))
现在,我觉得有一种方法可以告诉SQLAlchemy把你的对象变成一个“傻乎乎”的对象,这个对象和数据库没有任何连接,看起来和我刚才做的很像。不过我不知道具体是什么方法。