像所有CRUD一样,我需要将一些数据写入表中。当我将新数据写入表格时,一切都像魅力一样。当我需要编写表中已存在的数据时(实际上使用相同的主键更新某些数据),问题就开始了。 数据似乎没有写入表格!我开始尝试使用session.merge()更新数据,但后来尝试了更强力的方法,查询表中的相同primary_key,删除它以及添加和刷新更改的对象。 在某些地方,如果基本的添加和冲洗失败,其余的不起作用。我很高兴在这里得到一个线索。
代码:
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 vs mssql 2005 with pyodbc 2.1.11和tg 2.1(事务管理器附带tg,我认为是基于事务)
答案 0 :(得分:0)
问题似乎是DBSession.rollback()
发出了所有add / flush的回滚,因为提交只发生在事务管理器transaction.commit()
的最后。
一个丑陋的黑客将在每次循环传递后调用transaction.commit()
。 mike bayer here 描述了一个可能更好的解决方案:从数据库获取chuncked数据,比较,更新,然后在没有session.rollback
的情况下提交。另一种解决方案是使用session.begin_nested()
构造将SAVEPOINTS
添加到会话中,因此回滚不会删除数据。