SQLAlchemy IntegrityError - PullRequest
       22

SQLAlchemy IntegrityError

0 голосов
/ 17 марта 2011

У меня проблема с использованием SQLAlchemy с PySide (PyQt).Я пытаюсь вызвать QtGui.QDialog, но когда я делаю это, SQLAlchemy выдает исключение:

Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\preo\preodb\dbviewandmodel.py", line 32, in rowCount
    return len(self.rows())    
  File "C:\Python27\lib\site-packages\preo\preodb\dbviewandmodel.py", line 30, in rows
    return self.tableobj.query.all()
  File "C:\Python27\lib\site-packages\sqlalchemy-0.6.6-py2.7.egg\sqlalchemy\orm\query.py", line 1579, in all
return list(self)
  File "C:\Python27\lib\site-packages\sqlalchemy-0.6.6-py2.7.egg\sqlalchemy\orm\query.py", line 1688, in __iter__
    self.session._autoflush()
  File "C:\Python27\lib\site-packages\sqlalchemy-0.6.6-py2.7.egg\sqlalchemy\orm\session.py", line 862, in _autoflush
    self.flush()
  File "C:\Python27\lib\site-packages\sqlalchemy-0.6.6-py2.7.egg\sqlalchemy\orm\session.py", line 1388, in flush
    self._flush(objects)
  File "C:\Python27\lib\site-packages\sqlalchemy-0.6.6-py2.7.egg\sqlalchemy\orm\session.py", line 1469, in _flush
    flush_context.execute()
  File "C:\Python27\lib\site-packages\sqlalchemy-0.6.6-py2.7.egg\sqlalchemy\orm\unitofwork.py", line 302, in execute
    rec.execute(self)
  File "C:\Python27\lib\site-packages\sqlalchemy-0.6.6-py2.7.egg\sqlalchemy\orm\unitofwork.py", line 446, in execute
    uow
  File "C:\Python27\lib\site-packages\sqlalchemy-0.6.6-py2.7.egg\sqlalchemy\orm\mapper.py", line 1878, in _save_obj
    execute(statement, params)
  File "C:\Python27\lib\site-packages\sqlalchemy-0.6.6-py2.7.egg\sqlalchemy\engine\base.py", line 1191, in execute
    params)
  File "C:\Python27\lib\site-packages\sqlalchemy-0.6.6-py2.7.egg\sqlalchemy\engine\base.py", line 1271, in _execute_clauseelement
    return self.__execute_context(context)
  File "C:\Python27\lib\site-packages\sqlalchemy-0.6.6-py2.7.egg\sqlalchemy\engine\base.py", line 1302, in __execute_context
    context.parameters[0], context=context)
  File "C:\Python27\lib\site-packages\sqlalchemy-0.6.6-py2.7.egg\sqlalchemy\engine\base.py", line 1401, in _cursor_execute
    context)
  File "C:\Python27\lib\site-packages\sqlalchemy-0.6.6-py2.7.egg\sqlalchemy\engine\base.py", line 1394, in _cursor_execute
    context)
  File "C:\Python27\lib\site-packages\sqlalchemy-0.6.6-py2.7.egg\sqlalchemy\engine\default.py", line 299, in do_execute
    cursor.execute(statement, parameters)
sqlalchemy.exc.IntegrityError: (IntegrityError) ('23000', "[23000] [Microsoft][ODBC
SQL Server Driver][SQL Server]Violation of UNIQUE KEY
constraint 'UQ__users__F3DBC5720DAF0CB0'. Cannot insert duplicate key in
object 'dbo.users'. (2627) (SQLExecDirectW); [01000] [Microsoft][ODBC SQL Server
Driver][SQL Server]The statement has been terminated. (3621)") u'INSERT INTO users
(username, fullname, email, passwordmd5) OUTPUT inserted.id VALUES (?, ?, ?, ?)'
(None, None, None, None)

Это особенно беспокоит, потому что у меня нет нигде кода, который даже пытается вставить записив SQL;Я только пытаюсь запросить данные из базы данных.На самом деле, моя модель БД доступна только для чтения относительно того, что делает PySide / PyQt (то есть я использую QtGui.QTableView модель / представление, и в этой модели нет функции insertRows).

Я понятия не имею, что происходит или как ее решить - опять же, у меня нет кода для изменения записей SQL вообще, но все же SQLAlchemy пытается вставить пустые записи в одну из моих таблиц SQL.Все, что я вижу на заднем плане, это модель данных QTableView, которая запрашивает базу данных ОЧЕНЬ МНОГО.Просто кажется, что когда я выскакиваю это QDialog (в котором есть некоторый код для запроса некоторого столбца таблицы), эта ошибка генерируется.Как ни странно, это не согласуется, иногда всплывающее окно появляется первым перед исключением, иногда всплывающее окно появляется после исключения.При нормальных обстоятельствах модель данных QTableView прекрасно работает, только когда я не выхожу в это диалоговое окно (и по иронии судьбы, всплывающее окно вообще не использует QTableView, просто стандартные виджеты, такие как QLineEdit, QTextEdit и т. Д.)

Если это поможет, я использую Python 2.7 с SQLAlchemy 0.6.6 (также с Elixir 0.7.1) и PySide 1.0.0 (и PyQt4 4.8.3).Я на Windows 7 с использованием SQL 2008 R2 (Express).И да, я попытался перезагрузить компьютер, но проблема все еще возникает после перезагрузки.Я не хотел бы публиковать больше кода, потому что у меня его много в этом конкретном проекте, и я не могу придавить этой проблеме ничего конкретного.

Я надеюсь, что кто-то может знать о странностях в SQLAlchemy и /или PyQt, которые могут быть связаны с этим.Я также надеюсь, что смогу продолжать использовать SQLAlchemy, поскольку у меня есть большая модель данных;На данный момент я не хочу отказываться от этого и использовать возможности SQL PyQt.

1 Ответ

0 голосов
/ 17 марта 2011

Мне удалось решить эту проблему, но мне все еще не совсем понятно, почему SQLAlchemy пытался вставить строки в мою базу данных - это действительно беспокоит меня, но это больше не происходит.

Во всяком случае, то, что, как мне кажется, происходило, было связано с моей моделью данных SQLAlchemy и тем, как я к ней обращался, вот фрагмент этой модели:

from elixir import *

metadata.bind = 'mssql+pyodbc://username:password/dbname'
metadata.bind.echo = False

class Users(Entity):
    using_options(tablename = 'users')
    username = Field(String(50), unique=True)
    fullname = Field(String(255))
    email = Field(String(255))
    passwordmd5 = Field(String(32))
    def __repr__(self):
        return "<Users ({})({})({})>".format(self.username, self.fullname, self.email)
    def prettyname(self):
        return {'username':'User Name', 'fullname':'Full Name', 'email':'Email Address', 'passwordmd5':'$hidden$'}

В моем коде мне был нужен способ получить «красивые» имена меток для GUI без необходимости жесткого кодирования этого в GUI (я пытался создать динамический способ создания форм GUI). Итак, я добавил метод 'prettyname' в свою модель данных, чтобы дать мне некоторые специфичные для приложения метаданные в этой модели данных. Все, что я делаю, это возвращаю словарь предметов.

У меня была вторичная проблема: иногда мне нужно было получать эти данные из экземпляра класса для пользователей, а иногда для результата запроса для пользователей (например, Users.get_by (id = 1)). Как оказалось, получение этих данных должно было осуществляться двумя способами. В экземплярах класса мне нужно было получить значение следующим образом:

prettyname = Users().prettyname()['username']

Но когда я использовал результаты запроса, это было:

prettyname = queryresult.prettyname()['username']

SQLAlchemy, похоже, имеет реальную проблему, когда я использовал предыдущий метод (метод экземпляра класса) - так как он использовался каждый раз, когда я видел сбой. Когда я использовал последний экземпляр, я никогда не видел сбоя. Тем не менее мне нужен был доступ к этим метаданным в экземпляре класса.

Исправление, или я должен сказать, что выяснилось, чтобы исправить это, пришло из другой статьи Stackoverflow (спасибо всем в Stackoverflow - я был бы ничем без вас). Я изменил структуру dbmodel:

class Users(Entity):
    using_options(tablename = 'users')
    username = Field(String(50), unique=True, info={'prettyname':'User Name'})
    fullname = Field(String(255), info={'prettyname':'Full Name'})
    email = Field(String(255), info={'prettyname':'Email Address'})
    passwordmd5 = Field(String(32), info={'hidden':True})
    def __repr__(self):
        return "<Users ({})({})({})>".format(self.username, self.fullname, self.email)

Это позволяет мне использовать общий метод самоанализа для получения словарных данных в аргументе info, независимо от того, смотрю я на экземпляр класса или результат запроса. В этом случае я использую метод «.table» для класса или результата запроса, затем получаю нужный мне столбец (.c), затем использую метод .info этого столбца для возврата словаря.

В любом случае, теперь SQLAlchemy больше не пытается произвольно вставлять строки в базу данных.

...