0

像所有 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()

使用带有 pyodbc 2.1.11 和 tg 2.1 的 sqlalchemy 0.7.3 vs mssql 2005(事务管理器带有 tg,我认为是基于事务的)

4

1 回答 1

0

问题似乎是DBSession.rollback()所有添加/刷新的回滚问题,因为提交仅在事务管理器的最后发生transaction.commit()
一个丑陋的黑客将是transaction.commit()在每次循环通过后调用。mike bayer在这里描述了一个可能更好的解决方案:从数据库中获取分块数据,比较,更新,然后在没有session.rollback. 另一种解决方案是使用session.begin_nested()构造添加SAVEPOINTS到会话中,因此回滚不会删除数据。

于 2013-03-19T07:04:59.100 回答