sqlalchemy在尝试更新数据时未能在某个位置提交(但悄悄失败)
就像所有的CRUD一样,我需要向表中写入一些数据。当我向表中写入新数据时,一切都很顺利。当我需要写入表中已经存在的数据(实际上使用相同的主键更新一些数据)时,问题就开始了。 数据似乎没有写入到表中!我开始尝试使用session.merge()更新数据,但后来尝试了一种更为暴力的方法,即在表中查询相同的主键,删除它,并添加和刷新更改的对象。 在某些情况下,如果基本的添加和刷新失败,其余的就不起作用。我很高兴在这里得到线索 守则:sqlalchemy在尝试更新数据时未能在某个位置提交(但悄悄失败),sqlalchemy,turbogears2,Sqlalchemy,Turbogears2,就像所有的CRUD一样,我需要向表中写入一些数据。当我向表中写入新数据时,一切都很顺利。当我需要写入表中已经存在的数据(实际上使用相同的主键更新一些数据)时,问题就开始了。 数据似乎没有写入到表中!我开始尝试使用session.merge()更新数据,但后来尝试了一种更为暴力的方法,即在表中查询相同的主键,删除它,并添加和刷新更改的对象。 在某些情况下,如果基本的添加和刷新失败,其余的就不起作用。我很高兴在这里得到线索 守则: def flush(obj_Instance, id): """ t
def flush(obj_Instance, id):
"""
taking care of the sqlalchemy flushing
params:
Instance: an object Instance to flush into
id: the unique object instance id
"""
DBSession2.add(obj_Instance)
try:
try:
DBSession2.flush()
print ("flushed:", str(obj_Instance))
except (FlushError, IntegrityError) as err:
DBSession2.rollback()
if ('conflicts with persistent instance' in str(err)) or ('Duplicate key was ignored' in str(err)):
transaction.begin()
#my original slick take:
DBSession2.merge(obj_instance) # but after it failed to update correctly I changed to a more brute force approach
#DBSession2.flush() #to save the merge
#from here on trying to brute force it
#saving for further reference - another try
newInstance = deepcopy(obj_Instance)
print ("deleting: %s" % id)
DBSession2.query(type(obj_Instance)).filter_by(ids = id).delete()
DBSession2.flush() #at this point, I was so desperate for this to work I literated the code with flush commands.
DBSession2.add(newInstance)
DBSession2.flush()
return
else:
raise #handling the case of the same key problem isn't the source of conflicts
except Exception as err: # supposed to find out the error type and message
# the code doesn't get here, only in real exceptions it was planned to catch, 3 rows in 10,000 uploaded to the db
#TODO: make this less general and more specific
print str(err)
write_log(num=id, msg="some sql or sqlalchemy error use num %s as id identifier with object: %s" % (id, obj_Instance.name), timestamp=
datetime.now(), errtype="sql error", log=str(err))
DBSession2.rollback()
transaction.begin()
使用sqlalchemy 0.7.3与mssql 2005以及pyodbc 2.1.11和tg 2.1(事务管理器随附tg,我认为是基于事务的)问题似乎在于
DBSession.rollback()
会回滚所有的添加/刷新,因为只有在事务管理器transaction.commit()的最后才会进行提交
一个丑陋的方法是在每次循环传递后调用
transaction.commit()
。mike bayer描述了一个可能更好的解决方案:从数据库获取数据,比较、更新,然后提交,而无需会话。回滚。另一种解决方案是使用session.begin_nested()
构造将保存点添加到会话中,这样回滚就不会擦除数据