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()

sqlalchemy 0.7.3 と mssql 2005 を pyodbc 2.1.11 および tg 2.1 で使用する (トランザクション マネージャーには tg が付属しており、トランザクションに基づいていると思います)

4

1 に答える 1

0

問題はDBSession.rollback()、コミットがトランザクション マネージャーで最後にのみ発生するため、すべての追加/フラッシュのロールバックを発行することtransaction.commit()です。
醜いハックはtransaction.commit()、すべてのループパスの後に呼び出すことです。おそらくより良い解決策は、mike bayer hereによって説明されました。データベースからチャンクされたデータを取得し、比較、更新してからコミットせずにコミットしますsession.rollback。別の解決策は、session.begin_nested()コンストラクトを使用SAVEPOINTSしてセッションに追加することです。これにより、ロールバックによってデータが消去されなくなります。

于 2013-03-19T07:04:59.100 に答える